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