Branch data Line data Source code
1 : : #include <stdio.h>
2 : : #include <stdlib.h>
3 : : #include <string.h>
4 : :
5 : : #include "py/obj.h"
6 : : #include "py/objfun.h"
7 : : #include "py/objint.h"
8 : : #include "py/objstr.h"
9 : : #include "py/runtime.h"
10 : : #include "py/stackctrl.h"
11 : : #include "py/gc.h"
12 : : #include "py/repl.h"
13 : : #include "py/mpz.h"
14 : : #include "py/builtin.h"
15 : : #include "py/emit.h"
16 : : #include "py/formatfloat.h"
17 : : #include "py/ringbuf.h"
18 : : #include "py/pairheap.h"
19 : : #include "py/stream.h"
20 : : #include "py/binary.h"
21 : : #include "py/bc.h"
22 : :
23 : : // expected output of this file is found in extra_coverage.py.exp
24 : :
25 : : #if defined(MICROPY_UNIX_COVERAGE)
26 : :
27 : : // stream testing object
28 : : typedef struct _mp_obj_streamtest_t {
29 : : mp_obj_base_t base;
30 : : uint8_t *buf;
31 : : size_t len;
32 : : size_t pos;
33 : : int error_code;
34 : : } mp_obj_streamtest_t;
35 : :
36 : 6 : static mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) {
37 : 6 : mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
38 : 6 : mp_buffer_info_t bufinfo;
39 : 6 : mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
40 : 6 : o->buf = m_new(uint8_t, bufinfo.len);
41 : 6 : memcpy(o->buf, bufinfo.buf, bufinfo.len);
42 : 6 : o->len = bufinfo.len;
43 : 6 : o->pos = 0;
44 : 6 : return mp_const_none;
45 : : }
46 : : static MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf);
47 : :
48 : 6 : static mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) {
49 : 6 : mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
50 : 6 : o->error_code = mp_obj_get_int(err_in);
51 : 6 : return mp_const_none;
52 : : }
53 : : static MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error);
54 : :
55 : 22 : static mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
56 : 22 : mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
57 [ + + ]: 22 : if (o->pos < o->len) {
58 [ + + ]: 10 : if (size > o->len - o->pos) {
59 : 4 : size = o->len - o->pos;
60 : : }
61 : 10 : memcpy(buf, o->buf + o->pos, size);
62 : 10 : o->pos += size;
63 : 10 : return size;
64 [ + - ]: 12 : } else if (o->error_code == 0) {
65 : : return 0;
66 : : } else {
67 : 12 : *errcode = o->error_code;
68 : 12 : return MP_STREAM_ERROR;
69 : : }
70 : : }
71 : :
72 : 6 : static mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
73 : 6 : mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
74 : 6 : (void)buf;
75 : 6 : (void)size;
76 : 6 : *errcode = o->error_code;
77 : 6 : return MP_STREAM_ERROR;
78 : : }
79 : :
80 : 4 : static mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
81 : 4 : mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
82 : 4 : (void)arg;
83 : 4 : (void)request;
84 : 4 : (void)errcode;
85 [ + + ]: 4 : if (o->error_code != 0) {
86 : 2 : *errcode = o->error_code;
87 : 2 : return MP_STREAM_ERROR;
88 : : }
89 : : return 0;
90 : : }
91 : :
92 : : static const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
93 : : { MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) },
94 : : { MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) },
95 : : { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
96 : : { MP_ROM_QSTR(MP_QSTR_read1), MP_ROM_PTR(&mp_stream_read1_obj) },
97 : : { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
98 : : { MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) },
99 : : { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
100 : : { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
101 : : { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
102 : : };
103 : :
104 : : static MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
105 : :
106 : : static const mp_stream_p_t fileio_stream_p = {
107 : : .read = stest_read,
108 : : .write = stest_write,
109 : : .ioctl = stest_ioctl,
110 : : };
111 : :
112 : : static MP_DEFINE_CONST_OBJ_TYPE(
113 : : mp_type_stest_fileio,
114 : : MP_QSTR_stest_fileio,
115 : : MP_TYPE_FLAG_NONE,
116 : : protocol, &fileio_stream_p,
117 : : locals_dict, &rawfile_locals_dict
118 : : );
119 : :
120 : : // stream read returns non-blocking error
121 : 2 : static mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
122 : 2 : (void)o_in;
123 : 2 : (void)buf;
124 : 2 : (void)size;
125 : 2 : *errcode = MP_EAGAIN;
126 : 2 : return MP_STREAM_ERROR;
127 : : }
128 : :
129 : : static const mp_rom_map_elem_t rawfile_locals_dict_table2[] = {
130 : : { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
131 : : };
132 : :
133 : : static MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2);
134 : :
135 : : static const mp_stream_p_t textio_stream_p2 = {
136 : : .read = stest_read2,
137 : : .write = NULL,
138 : : .is_text = true,
139 : : };
140 : :
141 : : static MP_DEFINE_CONST_OBJ_TYPE(
142 : : mp_type_stest_textio2,
143 : : MP_QSTR_stest_textio2,
144 : : MP_TYPE_FLAG_NONE,
145 : : protocol, &textio_stream_p2,
146 : : locals_dict, &rawfile_locals_dict2
147 : : );
148 : :
149 : : // str/bytes objects without a valid hash
150 : : static const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte *)"0123456789"};
151 : : static const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte *)"0123456789"};
152 : :
153 : 62 : static int pairheap_lt(mp_pairheap_t *a, mp_pairheap_t *b) {
154 : 62 : return (uintptr_t)a < (uintptr_t)b;
155 : : }
156 : :
157 : : // ops array contain operations: x>=0 means push(x), x<0 means delete(-x)
158 : 12 : static void pairheap_test(size_t nops, int *ops) {
159 : 12 : mp_pairheap_t node[8];
160 [ + + ]: 108 : for (size_t i = 0; i < MP_ARRAY_SIZE(node); ++i) {
161 : 96 : mp_pairheap_init_node(pairheap_lt, &node[i]);
162 : : }
163 : 12 : mp_pairheap_t *heap = mp_pairheap_new(pairheap_lt);
164 : 12 : mp_printf(&mp_plat_print, "create:");
165 [ + + ]: 88 : for (size_t i = 0; i < nops; ++i) {
166 [ + + ]: 76 : if (ops[i] >= 0) {
167 : 60 : heap = mp_pairheap_push(pairheap_lt, heap, &node[ops[i]]);
168 : : } else {
169 : 16 : heap = mp_pairheap_delete(pairheap_lt, heap, &node[-ops[i]]);
170 : : }
171 [ + + ]: 76 : if (mp_pairheap_is_empty(pairheap_lt, heap)) {
172 : 4 : mp_printf(&mp_plat_print, " -");
173 : : } else {
174 : 72 : mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]);
175 : 76 : ;
176 : : }
177 : : }
178 : 12 : mp_printf(&mp_plat_print, "\npop all:");
179 [ + + ]: 58 : while (!mp_pairheap_is_empty(pairheap_lt, heap)) {
180 : 46 : mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]);
181 : 46 : ;
182 : 46 : heap = mp_pairheap_pop(pairheap_lt, heap);
183 : : }
184 : 12 : mp_printf(&mp_plat_print, "\n");
185 : 12 : }
186 : :
187 : : // function to run extra tests for things that can't be checked by scripts
188 : 2 : static mp_obj_t extra_coverage(void) {
189 : : // mp_printf (used by ports that don't have a native printf)
190 : : {
191 : 2 : mp_printf(&mp_plat_print, "# mp_printf\n");
192 : 2 : mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign
193 : 2 : mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding
194 : 2 : mp_printf(&mp_plat_print, "%ld\n", 123); // long
195 : 2 : mp_printf(&mp_plat_print, "%lx\n", 0x123); // long hex
196 : 2 : mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex
197 : 2 : 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
198 : 2 : mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision
199 : 2 : mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools
200 : : #ifndef NDEBUG
201 : 2 : mp_printf(&mp_plat_print, "%s\n", NULL); // null string
202 : : #else
203 : : mp_printf(&mp_plat_print, "(null)\n"); // without debugging mp_printf won't check for null
204 : : #endif
205 : 2 : mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed
206 : 2 : mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned
207 : 2 : mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned
208 : 2 : mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned
209 : 2 : mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier
210 : 2 : mp_printf(&mp_plat_print, "%%\n"); // literal % character
211 : : }
212 : :
213 : : // GC
214 : : {
215 : 2 : mp_printf(&mp_plat_print, "# GC\n");
216 : :
217 : : // calling gc_free while GC is locked
218 : 2 : gc_lock();
219 : 2 : gc_free(NULL);
220 : 2 : gc_unlock();
221 : :
222 : : // using gc_realloc to resize to 0, which means free the memory
223 : 2 : void *p = gc_alloc(4, false);
224 : 2 : mp_printf(&mp_plat_print, "%p\n", gc_realloc(p, 0, false));
225 : :
226 : : // calling gc_nbytes with a non-heap pointer
227 : 2 : mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL));
228 : : }
229 : :
230 : : // GC initialisation and allocation stress test, to check the logic behind ALLOC_TABLE_GAP_BYTE
231 : : // (the following test should fail when ALLOC_TABLE_GAP_BYTE=0)
232 : : {
233 : 2 : mp_printf(&mp_plat_print, "# GC part 2\n");
234 : :
235 : : // check the GC is unlocked and save its state
236 [ - + ]: 2 : assert(MP_STATE_THREAD(gc_lock_depth) == 0);
237 : 2 : mp_state_mem_t mp_state_mem_orig = mp_state_ctx.mem;
238 : :
239 : : // perform the test
240 : 2 : unsigned heap_size = 64 * MICROPY_BYTES_PER_GC_BLOCK;
241 [ + + ]: 4098 : for (unsigned j = 0; j < 256 * MP_BYTES_PER_OBJ_WORD; ++j) {
242 : 4096 : char *heap = calloc(heap_size, 1);
243 : 4096 : gc_init(heap, heap + heap_size);
244 : :
245 : 4096 : m_malloc(MICROPY_BYTES_PER_GC_BLOCK);
246 : 4096 : void *o = gc_alloc(MICROPY_BYTES_PER_GC_BLOCK, GC_ALLOC_FLAG_HAS_FINALISER);
247 : 4096 : ((mp_obj_base_t *)o)->type = NULL; // ensure type is cleared so GC doesn't look for finaliser
248 [ + - ]: 507904 : for (unsigned i = 0; i < heap_size / MICROPY_BYTES_PER_GC_BLOCK; ++i) {
249 : 507904 : void *p = m_malloc_maybe(MICROPY_BYTES_PER_GC_BLOCK);
250 [ + + ]: 507904 : if (!p) {
251 : : break;
252 : : }
253 : 503808 : *(void **)p = o;
254 : 503808 : o = p;
255 : : }
256 : 4096 : gc_collect();
257 : 4096 : free(heap);
258 : 4096 : heap_size += MICROPY_BYTES_PER_GC_BLOCK / 16;
259 : : }
260 : 2 : mp_printf(&mp_plat_print, "pass\n");
261 : :
262 : : // restore the GC state (the original heap)
263 : 2 : mp_state_ctx.mem = mp_state_mem_orig;
264 : : }
265 : :
266 : : // tracked allocation
267 : : {
268 : : #define NUM_PTRS (8)
269 : : #define NUM_BYTES (128)
270 : : #define FLIP_POINTER(p) ((uint8_t *)((uintptr_t)(p) ^ 0x0f))
271 : :
272 : 2 : mp_printf(&mp_plat_print, "# tracked allocation\n");
273 : 2 : mp_printf(&mp_plat_print, "m_tracked_head = %p\n", MP_STATE_VM(m_tracked_head));
274 : :
275 : 2 : uint8_t *ptrs[NUM_PTRS];
276 : :
277 : : // allocate memory blocks
278 [ + + ]: 18 : for (size_t i = 0; i < NUM_PTRS; ++i) {
279 : 16 : ptrs[i] = m_tracked_calloc(1, NUM_BYTES);
280 : 16 : bool all_zero = true;
281 [ + + ]: 2064 : for (size_t j = 0; j < NUM_BYTES; ++j) {
282 [ + - ]: 2048 : if (ptrs[i][j] != 0) {
283 : : all_zero = false;
284 : : break;
285 : : }
286 : 2048 : ptrs[i][j] = j;
287 : : }
288 : 16 : mp_printf(&mp_plat_print, "%d %d\n", i, all_zero);
289 : :
290 : : // hide the pointer from the GC and collect
291 : 16 : ptrs[i] = FLIP_POINTER(ptrs[i]);
292 : 16 : gc_collect();
293 : : }
294 : :
295 : : // check the memory blocks have the correct content
296 [ + + ]: 18 : for (size_t i = 0; i < NUM_PTRS; ++i) {
297 : 2064 : bool correct_contents = true;
298 [ + + ]: 2064 : for (size_t j = 0; j < NUM_BYTES; ++j) {
299 [ + - ]: 2048 : if (FLIP_POINTER(ptrs[i])[j] != j) {
300 : : correct_contents = false;
301 : : break;
302 : : }
303 : : }
304 : 16 : mp_printf(&mp_plat_print, "%d %d\n", i, correct_contents);
305 : : }
306 : :
307 : : // free the memory blocks
308 [ + + ]: 18 : for (size_t i = 0; i < NUM_PTRS; ++i) {
309 : 16 : m_tracked_free(FLIP_POINTER(ptrs[i]));
310 : : }
311 : :
312 : 2 : mp_printf(&mp_plat_print, "m_tracked_head = %p\n", MP_STATE_VM(m_tracked_head));
313 : : }
314 : :
315 : : // vstr
316 : : {
317 : 2 : mp_printf(&mp_plat_print, "# vstr\n");
318 : 2 : vstr_t *vstr = vstr_new(16);
319 : 2 : vstr_hint_size(vstr, 32);
320 : 2 : vstr_add_str(vstr, "ts");
321 : 2 : vstr_ins_byte(vstr, 1, 'e');
322 : 2 : vstr_ins_char(vstr, 3, 't');
323 : 2 : vstr_ins_char(vstr, 10, 's');
324 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
325 : :
326 : 2 : vstr_cut_head_bytes(vstr, 2);
327 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
328 : :
329 : 2 : vstr_cut_tail_bytes(vstr, 10);
330 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
331 : :
332 : 2 : vstr_printf(vstr, "t%cst", 'e');
333 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
334 : :
335 : 2 : vstr_cut_out_bytes(vstr, 3, 10);
336 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
337 : :
338 : 2 : VSTR_FIXED(fix, 4);
339 : 2 : nlr_buf_t nlr;
340 [ + + ]: 2 : if (nlr_push(&nlr) == 0) {
341 : 2 : vstr_add_str(&fix, "large");
342 : 0 : nlr_pop();
343 : : } else {
344 : 2 : mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
345 : : }
346 : :
347 : 2 : fix.len = fix.alloc;
348 [ + + ]: 2 : if (nlr_push(&nlr) == 0) {
349 : 2 : vstr_null_terminated_str(&fix);
350 : 0 : nlr_pop();
351 : : } else {
352 : 2 : mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
353 : : }
354 : : }
355 : :
356 : : // repl autocomplete
357 : : {
358 : 2 : mp_printf(&mp_plat_print, "# repl\n");
359 : :
360 : 2 : const char *str;
361 : 2 : size_t len = mp_repl_autocomplete("__n", 3, &mp_plat_print, &str); // expect "ame__"
362 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
363 : :
364 : 2 : len = mp_repl_autocomplete("im", 2, &mp_plat_print, &str); // expect "port"
365 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
366 : 2 : mp_repl_autocomplete("import ", 7, &mp_plat_print, &str); // expect the list of builtins
367 : 2 : len = mp_repl_autocomplete("import ti", 9, &mp_plat_print, &str); // expect "me"
368 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
369 : 2 : mp_repl_autocomplete("import m", 8, &mp_plat_print, &str); // expect "micropython machine math"
370 : :
371 : 2 : mp_store_global(MP_QSTR_sys, mp_import_name(MP_QSTR_sys, mp_const_none, MP_OBJ_NEW_SMALL_INT(0)));
372 : 2 : mp_repl_autocomplete("sys.", 4, &mp_plat_print, &str); // expect dir(sys)
373 : 2 : len = mp_repl_autocomplete("sys.impl", 8, &mp_plat_print, &str); // expect "ementation"
374 : 2 : mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
375 : : }
376 : :
377 : : // attrtuple
378 : : {
379 : 2 : mp_printf(&mp_plat_print, "# attrtuple\n");
380 : :
381 : 2 : static const qstr fields[] = {MP_QSTR_start, MP_QSTR_stop, MP_QSTR_step};
382 : 2 : static const mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(2), MP_OBJ_NEW_SMALL_INT(3)};
383 : 2 : mp_obj_print_helper(&mp_plat_print, mp_obj_new_attrtuple(fields, 3, items), PRINT_REPR);
384 : 2 : mp_printf(&mp_plat_print, "\n");
385 : : }
386 : :
387 : : // str
388 : : {
389 : 2 : mp_printf(&mp_plat_print, "# str\n");
390 : :
391 : : // intern string
392 : 2 : mp_printf(&mp_plat_print, "%d\n", mp_obj_is_qstr(mp_obj_str_intern(mp_obj_new_str_from_cstr("intern me"))));
393 : : }
394 : :
395 : : // bytearray
396 : : {
397 : 2 : mp_printf(&mp_plat_print, "# bytearray\n");
398 : :
399 : : // create a bytearray via mp_obj_new_bytearray
400 : 2 : mp_buffer_info_t bufinfo;
401 : 2 : mp_get_buffer_raise(mp_obj_new_bytearray(4, "data"), &bufinfo, MP_BUFFER_RW);
402 : 2 : mp_printf(&mp_plat_print, "%.*s\n", bufinfo.len, bufinfo.buf);
403 : : }
404 : :
405 : : // mpz
406 : : {
407 : 2 : mp_printf(&mp_plat_print, "# mpz\n");
408 : :
409 : 2 : mp_uint_t value;
410 : 2 : mpz_t mpz;
411 : 2 : mpz_init_zero(&mpz);
412 : :
413 : : // mpz_as_uint_checked, with success
414 : 2 : mpz_set_from_int(&mpz, 12345678);
415 : 2 : mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
416 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value);
417 : :
418 : : // mpz_as_uint_checked, with negative arg
419 : 2 : mpz_set_from_int(&mpz, -1);
420 : 2 : mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
421 : :
422 : : // mpz_as_uint_checked, with overflowing arg
423 : 2 : mpz_set_from_int(&mpz, 1);
424 : 2 : mpz_shl_inpl(&mpz, &mpz, 70);
425 : 2 : mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
426 : :
427 : : // mpz_set_from_float with inf as argument
428 : 2 : mpz_set_from_float(&mpz, 1.0 / 0.0);
429 : 2 : mpz_as_uint_checked(&mpz, &value);
430 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value);
431 : :
432 : : // mpz_set_from_float with 0 as argument
433 : 2 : mpz_set_from_float(&mpz, 0);
434 : 2 : mpz_as_uint_checked(&mpz, &value);
435 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value);
436 : :
437 : : // mpz_set_from_float with 0<x<1 as argument
438 : 2 : mpz_set_from_float(&mpz, 1e-10);
439 : 2 : mpz_as_uint_checked(&mpz, &value);
440 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value);
441 : :
442 : : // mpz_set_from_float with 1<=x<2 as argument
443 : 2 : mpz_set_from_float(&mpz, 1.5);
444 : 2 : mpz_as_uint_checked(&mpz, &value);
445 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value);
446 : :
447 : : // mpz_set_from_float with 2<x as argument
448 : 2 : mpz_set_from_float(&mpz, 12345);
449 : 2 : mpz_as_uint_checked(&mpz, &value);
450 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value);
451 : :
452 : : // mpz_mul_inpl with dest==rhs, lhs!=rhs
453 : 2 : mpz_t mpz2;
454 : 2 : mpz_set_from_int(&mpz, 2);
455 : 2 : mpz_init_from_int(&mpz2, 3);
456 : 2 : mpz_mul_inpl(&mpz, &mpz2, &mpz);
457 : 2 : mpz_as_uint_checked(&mpz, &value);
458 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value);
459 : :
460 : : // mpz_not_inpl with argument==0, testing ~0
461 : 2 : mpz_set_from_int(&mpz, 0);
462 : 2 : mpz_not_inpl(&mpz, &mpz);
463 : 2 : mp_int_t value_signed;
464 : 2 : mpz_as_int_checked(&mpz, &value_signed);
465 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)value_signed);
466 : : }
467 : :
468 : : // runtime utils
469 : : {
470 : 2 : mp_printf(&mp_plat_print, "# runtime utils\n");
471 : :
472 : : // call mp_call_function_1_protected
473 : 2 : mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), MP_OBJ_NEW_SMALL_INT(1));
474 : : // call mp_call_function_1_protected with invalid args
475 : 2 : mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), mp_obj_new_str_from_cstr("abc"));
476 : :
477 : : // call mp_call_function_2_protected
478 : 2 : 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));
479 : : // call mp_call_function_2_protected with invalid args
480 : 2 : mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str_from_cstr("abc"), mp_obj_new_str_from_cstr("abc"));
481 : :
482 : : // mp_obj_int_get_checked with mp_obj_int_t that has a value that is a small integer
483 : 2 : mp_printf(&mp_plat_print, "%d\n", mp_obj_int_get_checked(mp_obj_int_new_mpz()));
484 : :
485 : : // mp_obj_int_get_uint_checked with non-negative small-int
486 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1)));
487 : :
488 : : // mp_obj_int_get_uint_checked with non-negative big-int
489 : 2 : mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(2)));
490 : :
491 : : // mp_obj_int_get_uint_checked with negative small-int (should raise exception)
492 : 2 : nlr_buf_t nlr;
493 [ + + ]: 2 : if (nlr_push(&nlr) == 0) {
494 : 2 : mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(-1));
495 : 0 : nlr_pop();
496 : : } else {
497 : 2 : mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
498 : : }
499 : :
500 : : // mp_obj_int_get_uint_checked with negative big-int (should raise exception)
501 [ + + ]: 2 : if (nlr_push(&nlr) == 0) {
502 : 2 : mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(-2));
503 : 0 : nlr_pop();
504 : : } else {
505 : 2 : mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
506 : : }
507 : :
508 : : // call mp_obj_new_exception_args (it's a part of the public C API and not used in the core)
509 : 2 : mp_obj_print_exception(&mp_plat_print, mp_obj_new_exception_args(&mp_type_ValueError, 0, NULL));
510 : : }
511 : :
512 : : // warning
513 : : {
514 : 2 : mp_emitter_warning(MP_PASS_CODE_SIZE, "test");
515 : : }
516 : :
517 : : // format float
518 : : {
519 : 2 : mp_printf(&mp_plat_print, "# format float\n");
520 : :
521 : : // format with inadequate buffer size
522 : 2 : char buf[5];
523 : 2 : mp_format_float(1, buf, sizeof(buf), 'g', 0, '+');
524 : 2 : mp_printf(&mp_plat_print, "%s\n", buf);
525 : :
526 : : // format with just enough buffer so that precision must be
527 : : // set from 0 to 1 twice
528 : 2 : char buf2[8];
529 : 2 : mp_format_float(1, buf2, sizeof(buf2), 'g', 0, '+');
530 : 2 : mp_printf(&mp_plat_print, "%s\n", buf2);
531 : :
532 : : // format where precision is trimmed to avoid buffer overflow
533 : 2 : mp_format_float(1, buf2, sizeof(buf2), 'e', 0, '+');
534 : 2 : mp_printf(&mp_plat_print, "%s\n", buf2);
535 : : }
536 : :
537 : : // binary
538 : : {
539 : 2 : mp_printf(&mp_plat_print, "# binary\n");
540 : :
541 : : // call function with float and double typecodes
542 : 2 : float far[1];
543 : 2 : double dar[1];
544 : 2 : mp_binary_set_val_array_from_int('f', far, 0, 123);
545 : 2 : mp_printf(&mp_plat_print, "%.0f\n", (double)far[0]);
546 : 2 : mp_binary_set_val_array_from_int('d', dar, 0, 456);
547 : 2 : mp_printf(&mp_plat_print, "%.0lf\n", dar[0]);
548 : : }
549 : :
550 : : // VM
551 : : {
552 : 2 : mp_printf(&mp_plat_print, "# VM\n");
553 : :
554 : : // call mp_execute_bytecode with invalid bytecode (should raise NotImplementedError)
555 : 2 : mp_module_context_t context;
556 : 2 : mp_obj_fun_bc_t fun_bc;
557 : 2 : fun_bc.context = &context;
558 : 2 : fun_bc.child_table = NULL;
559 : 2 : fun_bc.bytecode = (const byte *)"\x01"; // just needed for n_state
560 : 2 : mp_code_state_t *code_state = m_new_obj_var(mp_code_state_t, state, mp_obj_t, 1);
561 : 2 : code_state->fun_bc = &fun_bc;
562 : 2 : code_state->ip = (const byte *)"\x00"; // just needed for an invalid opcode
563 : 2 : code_state->sp = &code_state->state[0];
564 : 2 : code_state->exc_sp_idx = 0;
565 : 2 : code_state->old_globals = NULL;
566 : 2 : mp_vm_return_kind_t ret = mp_execute_bytecode(code_state, MP_OBJ_NULL);
567 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError);
568 : : }
569 : :
570 : : // scheduler
571 : : {
572 : 2 : mp_printf(&mp_plat_print, "# scheduler\n");
573 : :
574 : : // lock scheduler
575 : 2 : mp_sched_lock();
576 : :
577 : : // schedule multiple callbacks; last one should fail
578 [ + + ]: 12 : for (int i = 0; i < 5; ++i) {
579 : 10 : 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)));
580 : : }
581 : :
582 : : // test nested locking/unlocking
583 : 2 : mp_sched_lock();
584 : 2 : mp_sched_unlock();
585 : :
586 : : // shouldn't do anything while scheduler is locked
587 : 2 : mp_handle_pending(true);
588 : :
589 : : // unlock scheduler
590 : 2 : mp_sched_unlock();
591 : 2 : mp_printf(&mp_plat_print, "unlocked\n");
592 : :
593 : : // drain pending callbacks, and test mp_event_wait_indefinite(), mp_event_wait_ms()
594 : 2 : mp_event_wait_indefinite(); // the unix port only waits 500us in this call
595 [ + + ]: 8 : while (mp_sched_num_pending()) {
596 : 6 : mp_event_wait_ms(1);
597 : : }
598 : :
599 : : // setting the keyboard interrupt and raising it during mp_handle_pending
600 : 2 : mp_sched_keyboard_interrupt();
601 : 2 : nlr_buf_t nlr;
602 [ + + ]: 2 : if (nlr_push(&nlr) == 0) {
603 : 2 : mp_handle_pending(true);
604 : 0 : nlr_pop();
605 : : } else {
606 : 2 : mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
607 : : }
608 : :
609 : : // setting the keyboard interrupt (twice) and cancelling it during mp_handle_pending
610 : 2 : mp_sched_keyboard_interrupt();
611 : 2 : mp_sched_keyboard_interrupt();
612 : 2 : mp_handle_pending(false);
613 : :
614 : : // setting keyboard interrupt and a pending event (intr should be handled first)
615 : 2 : mp_sched_schedule(MP_OBJ_FROM_PTR(&mp_builtin_print_obj), MP_OBJ_NEW_SMALL_INT(10));
616 : 2 : mp_sched_keyboard_interrupt();
617 [ + + ]: 2 : if (nlr_push(&nlr) == 0) {
618 : 2 : mp_handle_pending(true);
619 : 0 : nlr_pop();
620 : : } else {
621 : 2 : mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
622 : : }
623 : 2 : mp_handle_pending(true);
624 : : }
625 : :
626 : : // ringbuf
627 : : {
628 : 2 : byte buf[100];
629 : 2 : ringbuf_t ringbuf = {buf, sizeof(buf), 0, 0};
630 : :
631 : 2 : mp_printf(&mp_plat_print, "# ringbuf\n");
632 : :
633 : : // Single-byte put/get with empty ringbuf.
634 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
635 : 2 : ringbuf_put(&ringbuf, 22);
636 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
637 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_get(&ringbuf));
638 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
639 : :
640 : : // Two-byte put/get with empty ringbuf.
641 : 2 : ringbuf_put16(&ringbuf, 0xaa55);
642 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
643 : 2 : mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
644 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
645 : :
646 : : // Two-byte put with full ringbuf.
647 [ + + ]: 200 : for (int i = 0; i < 99; ++i) {
648 : 198 : ringbuf_put(&ringbuf, i);
649 : : }
650 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
651 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb));
652 : : // Two-byte put with one byte free.
653 : 2 : ringbuf_get(&ringbuf);
654 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
655 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x3377));
656 : 2 : ringbuf_get(&ringbuf);
657 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
658 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0xcc99));
659 [ + + ]: 196 : for (int i = 0; i < 97; ++i) {
660 : 194 : ringbuf_get(&ringbuf);
661 : : }
662 : 2 : mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
663 : 2 : mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
664 : :
665 : : // Two-byte put with wrap around on first byte:
666 : 2 : ringbuf.iput = 0;
667 : 2 : ringbuf.iget = 0;
668 [ + + ]: 200 : for (int i = 0; i < 99; ++i) {
669 : 198 : ringbuf_put(&ringbuf, i);
670 : 198 : ringbuf_get(&ringbuf);
671 : : }
672 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb));
673 : 2 : mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
674 : :
675 : : // Two-byte put with wrap around on second byte:
676 : 2 : ringbuf.iput = 0;
677 : 2 : ringbuf.iget = 0;
678 [ + + ]: 198 : for (int i = 0; i < 98; ++i) {
679 : 196 : ringbuf_put(&ringbuf, i);
680 : 196 : ringbuf_get(&ringbuf);
681 : : }
682 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x22ff));
683 : 2 : mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
684 : :
685 : : // Two-byte get from empty ringbuf.
686 : 2 : ringbuf.iput = 0;
687 : 2 : ringbuf.iget = 0;
688 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf));
689 : :
690 : : // Two-byte get from ringbuf with one byte available.
691 : 2 : ringbuf.iput = 0;
692 : 2 : ringbuf.iget = 0;
693 : 2 : ringbuf_put(&ringbuf, 0xaa);
694 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf));
695 : :
696 : : // ringbuf_put_bytes() / ringbuf_get_bytes() functions.
697 : 2 : ringbuf.iput = 0;
698 : 2 : ringbuf.iget = 0;
699 : 2 : uint8_t *put = (uint8_t *)"abc123";
700 : 2 : uint8_t get[7] = {0};
701 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put_bytes(&ringbuf, put, 7));
702 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_get_bytes(&ringbuf, get, 7));
703 : 2 : mp_printf(&mp_plat_print, "%s\n", get);
704 : : // Prefill ringbuffer.
705 [ + + ]: 196 : for (size_t i = 0; i < sizeof(buf) - 3; ++i) {
706 : 194 : ringbuf_put(&ringbuf, i);
707 : : }
708 : : // Should fail - too full.
709 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put_bytes(&ringbuf, put, 7));
710 : : // Should fail - buffer too big.
711 : 2 : uint8_t large[sizeof(buf) + 5] = {0};
712 : 2 : mp_printf(&mp_plat_print, "%d\n", ringbuf_put_bytes(&ringbuf, large, sizeof(large)));
713 : : }
714 : :
715 : : // pairheap
716 : : {
717 : 2 : mp_printf(&mp_plat_print, "# pairheap\n");
718 : :
719 : : // Basic case.
720 : 2 : int t0[] = {0, 2, 1, 3};
721 : 2 : pairheap_test(MP_ARRAY_SIZE(t0), t0);
722 : :
723 : : // All pushed in reverse order.
724 : 2 : int t1[] = {7, 6, 5, 4, 3, 2, 1, 0};
725 : 2 : pairheap_test(MP_ARRAY_SIZE(t1), t1);
726 : :
727 : : // Basic deletion.
728 : 2 : int t2[] = {1, -1, -1, 1, 2, -2, 2, 3, -3};
729 : 2 : pairheap_test(MP_ARRAY_SIZE(t2), t2);
730 : :
731 : : // Deletion of first child that has next node (the -3).
732 : 2 : int t3[] = {1, 2, 3, 4, -1, -3};
733 : 2 : pairheap_test(MP_ARRAY_SIZE(t3), t3);
734 : :
735 : : // Deletion of node that's not first child (the -2).
736 : 2 : int t4[] = {1, 2, 3, 4, -2};
737 : 2 : pairheap_test(MP_ARRAY_SIZE(t4), t4);
738 : :
739 : : // Deletion of node that's not first child and has children (the -3).
740 : 2 : int t5[] = {3, 4, 5, 1, 2, -3};
741 : 2 : pairheap_test(MP_ARRAY_SIZE(t5), t5);
742 : : }
743 : :
744 : : // mp_obj_is_type and derivatives
745 : : {
746 : 2 : mp_printf(&mp_plat_print, "# mp_obj_is_type\n");
747 : :
748 : : // mp_obj_is_bool accepts only booleans
749 : 2 : mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_bool(mp_const_true), mp_obj_is_bool(mp_const_false));
750 : 2 : 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));
751 : :
752 : : // mp_obj_is_integer accepts ints and booleans
753 : 2 : 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)));
754 : 2 : mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_const_true), mp_obj_is_integer(mp_const_false));
755 : 2 : mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_obj_new_str_from_cstr("1")), mp_obj_is_integer(mp_const_none));
756 : :
757 : : // mp_obj_is_int accepts small int and object ints
758 [ + - + - : 4 : 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)));
+ - ]
759 : : }
760 : :
761 : : // Legacy stackctrl.h API, this has been replaced by cstack.h
762 : : {
763 : 2 : mp_printf(&mp_plat_print, "# stackctrl\n");
764 : 2 : char *old_stack_top = MP_STATE_THREAD(stack_top);
765 : 2 : size_t old_stack_limit = 0;
766 : 2 : size_t new_stack_limit = SIZE_MAX;
767 : : #if MICROPY_STACK_CHECK
768 : 2 : old_stack_limit = MP_STATE_THREAD(stack_limit);
769 : 2 : MP_STACK_CHECK();
770 : : #endif
771 : :
772 : 2 : mp_stack_ctrl_init(); // Will set stack top incorrectly
773 : 2 : mp_stack_set_top(old_stack_top); // ... and restore it
774 : :
775 : : #if MICROPY_STACK_CHECK
776 : 2 : mp_stack_set_limit(MP_STATE_THREAD(stack_limit));
777 : 2 : MP_STACK_CHECK();
778 : 2 : new_stack_limit = MP_STATE_THREAD(stack_limit);
779 : : #endif
780 : :
781 : : // Nothing should have changed
782 : 4 : mp_printf(&mp_plat_print, "%d %d\n",
783 : 2 : old_stack_top == MP_STATE_THREAD(stack_top),
784 : : MICROPY_STACK_CHECK == 0 || old_stack_limit == new_stack_limit);
785 : : }
786 : :
787 : 2 : mp_printf(&mp_plat_print, "# end coverage.c\n");
788 : :
789 : 2 : mp_obj_streamtest_t *s = mp_obj_malloc(mp_obj_streamtest_t, &mp_type_stest_fileio);
790 : 2 : s->buf = NULL;
791 : 2 : s->len = 0;
792 : 2 : s->pos = 0;
793 : 2 : s->error_code = 0;
794 : 2 : mp_obj_streamtest_t *s2 = mp_obj_malloc(mp_obj_streamtest_t, &mp_type_stest_textio2);
795 : :
796 : : // return a tuple of data for testing on the Python side
797 : 2 : 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)};
798 : 2 : return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items);
799 : : }
800 : : MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage);
801 : :
802 : : #endif
|