2015-05-07 19:19:56 -04:00
|
|
|
#include <stdio.h>
|
2017-01-15 23:04:53 -05:00
|
|
|
#include <string.h>
|
2015-05-07 19:19:56 -04:00
|
|
|
|
|
|
|
#include "py/obj.h"
|
2016-09-02 01:07:42 -04:00
|
|
|
#include "py/objstr.h"
|
2015-05-07 19:19:56 -04:00
|
|
|
#include "py/runtime.h"
|
2018-03-01 06:49:15 -05:00
|
|
|
#include "py/gc.h"
|
2015-05-07 19:19:56 -04:00
|
|
|
#include "py/repl.h"
|
2015-10-01 13:49:37 -04:00
|
|
|
#include "py/mpz.h"
|
2016-12-29 02:07:38 -05:00
|
|
|
#include "py/builtin.h"
|
2017-01-03 22:23:29 -05:00
|
|
|
#include "py/emit.h"
|
2017-01-04 19:12:05 -05:00
|
|
|
#include "py/formatfloat.h"
|
2021-04-23 15:26:42 -04:00
|
|
|
#include "py/ringbuf.h"
|
2017-01-15 23:04:53 -05:00
|
|
|
#include "py/stream.h"
|
2017-03-14 02:58:43 -04:00
|
|
|
#include "py/binary.h"
|
2018-02-27 00:17:10 -05:00
|
|
|
#include "py/bc.h"
|
2017-01-15 23:04:53 -05:00
|
|
|
|
2017-01-16 00:20:18 -05:00
|
|
|
#if defined(MICROPY_UNIX_COVERAGE)
|
|
|
|
|
2017-01-15 23:04:53 -05:00
|
|
|
// stream testing object
|
|
|
|
typedef struct _mp_obj_streamtest_t {
|
|
|
|
mp_obj_base_t base;
|
|
|
|
uint8_t *buf;
|
|
|
|
size_t len;
|
|
|
|
size_t pos;
|
|
|
|
int error_code;
|
|
|
|
} mp_obj_streamtest_t;
|
|
|
|
|
|
|
|
STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) {
|
|
|
|
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
|
|
|
|
mp_buffer_info_t bufinfo;
|
|
|
|
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
|
|
|
|
o->buf = m_new(uint8_t, bufinfo.len);
|
|
|
|
memcpy(o->buf, bufinfo.buf, bufinfo.len);
|
|
|
|
o->len = bufinfo.len;
|
|
|
|
o->pos = 0;
|
|
|
|
return mp_const_none;
|
|
|
|
}
|
|
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf);
|
|
|
|
|
|
|
|
STATIC mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) {
|
|
|
|
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
|
|
|
|
o->error_code = mp_obj_get_int(err_in);
|
|
|
|
return mp_const_none;
|
|
|
|
}
|
|
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error);
|
|
|
|
|
|
|
|
STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
|
|
|
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
|
|
|
|
if (o->pos < o->len) {
|
|
|
|
if (size > o->len - o->pos) {
|
|
|
|
size = o->len - o->pos;
|
|
|
|
}
|
|
|
|
memcpy(buf, o->buf + o->pos, size);
|
|
|
|
o->pos += size;
|
|
|
|
return size;
|
|
|
|
} else if (o->error_code == 0) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
*errcode = o->error_code;
|
|
|
|
return MP_STREAM_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
|
|
|
|
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
|
|
|
|
(void)buf;
|
|
|
|
(void)size;
|
|
|
|
*errcode = o->error_code;
|
|
|
|
return MP_STREAM_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
|
|
|
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
|
|
|
|
(void)arg;
|
|
|
|
(void)request;
|
|
|
|
(void)errcode;
|
|
|
|
if (o->error_code != 0) {
|
|
|
|
*errcode = o->error_code;
|
|
|
|
return MP_STREAM_ERROR;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_read1), MP_ROM_PTR(&mp_stream_read1_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
|
|
|
|
};
|
|
|
|
|
|
|
|
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
|
|
|
|
|
|
|
|
STATIC const mp_stream_p_t fileio_stream_p = {
|
protocols: Allow them to be (optionally) type-safe
Protocols are nice, but there is no way for C code to verify whether
a type's "protocol" structure actually implements some particular
protocol. As a result, you can pass an object that implements the
"vfs" protocol to one that expects the "stream" protocol, and the
opposite of awesomeness ensues.
This patch adds an OPTIONAL (but enabled by default) protocol identifier
as the first member of any protocol structure. This identifier is
simply a unique QSTR chosen by the protocol designer and used by each
protocol implementer. When checking for protocol support, instead of
just checking whether the object's type has a non-NULL protocol field,
use `mp_proto_get` which implements the protocol check when possible.
The existing protocols are now named:
protocol_framebuf
protocol_i2c
protocol_pin
protocol_stream
protocol_spi
protocol_vfs
(most of these are unused in CP and are just inherited from MP; vfs and
stream are definitely used though)
I did not find any crashing examples, but here's one to give a flavor of what
is improved, using `micropython_coverage`. Before the change,
the vfs "ioctl" protocol is invoked, and the result is not intelligible
as json (but it could have resulted in a hard fault, potentially):
>>> import uos, ujson
>>> u = uos.VfsPosix('/tmp')
>>> ujson.load(u)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: syntax error in JSON
After the change, the vfs object is correctly detected as not supporting
the stream protocol:
>>> ujson.load(p)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: stream operation not supported
2019-12-03 15:50:37 -05:00
|
|
|
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
|
2017-01-15 23:04:53 -05:00
|
|
|
.read = stest_read,
|
|
|
|
.write = stest_write,
|
|
|
|
.ioctl = stest_ioctl,
|
|
|
|
};
|
|
|
|
|
|
|
|
STATIC const mp_obj_type_t mp_type_stest_fileio = {
|
|
|
|
{ &mp_type_type },
|
|
|
|
.protocol = &fileio_stream_p,
|
2021-03-15 09:57:36 -04:00
|
|
|
.locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict,
|
2017-01-15 23:04:53 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// stream read returns non-blocking error
|
|
|
|
STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
|
|
|
(void)o_in;
|
|
|
|
(void)buf;
|
|
|
|
(void)size;
|
|
|
|
*errcode = MP_EAGAIN;
|
|
|
|
return MP_STREAM_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = {
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
|
|
|
};
|
|
|
|
|
|
|
|
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2);
|
|
|
|
|
|
|
|
STATIC const mp_stream_p_t textio_stream_p2 = {
|
protocols: Allow them to be (optionally) type-safe
Protocols are nice, but there is no way for C code to verify whether
a type's "protocol" structure actually implements some particular
protocol. As a result, you can pass an object that implements the
"vfs" protocol to one that expects the "stream" protocol, and the
opposite of awesomeness ensues.
This patch adds an OPTIONAL (but enabled by default) protocol identifier
as the first member of any protocol structure. This identifier is
simply a unique QSTR chosen by the protocol designer and used by each
protocol implementer. When checking for protocol support, instead of
just checking whether the object's type has a non-NULL protocol field,
use `mp_proto_get` which implements the protocol check when possible.
The existing protocols are now named:
protocol_framebuf
protocol_i2c
protocol_pin
protocol_stream
protocol_spi
protocol_vfs
(most of these are unused in CP and are just inherited from MP; vfs and
stream are definitely used though)
I did not find any crashing examples, but here's one to give a flavor of what
is improved, using `micropython_coverage`. Before the change,
the vfs "ioctl" protocol is invoked, and the result is not intelligible
as json (but it could have resulted in a hard fault, potentially):
>>> import uos, ujson
>>> u = uos.VfsPosix('/tmp')
>>> ujson.load(u)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: syntax error in JSON
After the change, the vfs object is correctly detected as not supporting
the stream protocol:
>>> ujson.load(p)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: stream operation not supported
2019-12-03 15:50:37 -05:00
|
|
|
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
|
2017-01-15 23:04:53 -05:00
|
|
|
.read = stest_read2,
|
|
|
|
.write = NULL,
|
|
|
|
.is_text = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
STATIC const mp_obj_type_t mp_type_stest_textio2 = {
|
|
|
|
{ &mp_type_type },
|
|
|
|
.protocol = &textio_stream_p2,
|
2021-03-15 09:57:36 -04:00
|
|
|
.locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict2,
|
2017-01-15 23:04:53 -05:00
|
|
|
};
|
|
|
|
|
2016-09-02 01:07:42 -04:00
|
|
|
// str/bytes objects without a valid hash
|
2021-03-15 09:57:36 -04:00
|
|
|
STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte *)"0123456789"};
|
|
|
|
STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte *)"0123456789"};
|
2016-09-02 01:07:42 -04:00
|
|
|
|
2015-05-07 19:19:56 -04:00
|
|
|
// function to run extra tests for things that can't be checked by scripts
|
2015-05-08 04:18:38 -04:00
|
|
|
STATIC mp_obj_t extra_coverage(void) {
|
2015-05-28 10:25:07 -04:00
|
|
|
// mp_printf (used by ports that don't have a native printf)
|
|
|
|
{
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "# mp_printf\n");
|
2015-05-28 10:25:07 -04:00
|
|
|
mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign
|
|
|
|
mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding
|
|
|
|
mp_printf(&mp_plat_print, "%ld\n", 123); // long
|
2017-12-18 23:01:17 -05:00
|
|
|
mp_printf(&mp_plat_print, "%lx\n", 0x123); // long hex
|
2015-05-28 10:25:07 -04:00
|
|
|
mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex
|
|
|
|
mp_printf(&mp_plat_print, "%.2s %.3s\n", "abc", "abc"); // fixed string precision
|
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision
|
|
|
|
mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools
|
2018-03-07 20:49:31 -05:00
|
|
|
#ifndef NDEBUG
|
2015-05-28 10:25:07 -04:00
|
|
|
mp_printf(&mp_plat_print, "%s\n", NULL); // null string
|
2018-03-07 20:49:31 -05:00
|
|
|
#else
|
|
|
|
mp_printf(&mp_plat_print, "(null)\n"); // without debugging mp_printf won't check for null
|
|
|
|
#endif
|
2016-02-01 10:08:42 -05:00
|
|
|
mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed
|
|
|
|
mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned
|
|
|
|
mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned
|
|
|
|
mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned
|
2017-06-29 22:25:42 -04:00
|
|
|
mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier
|
2021-04-22 20:55:39 -04:00
|
|
|
mp_printf(&mp_plat_print, "%%\n"); // literal % character
|
2015-05-28 10:25:07 -04:00
|
|
|
}
|
|
|
|
|
2018-03-01 06:49:15 -05:00
|
|
|
// GC
|
|
|
|
{
|
|
|
|
mp_printf(&mp_plat_print, "# GC\n");
|
|
|
|
|
|
|
|
// calling gc_free while GC is locked
|
|
|
|
gc_lock();
|
|
|
|
gc_free(NULL);
|
|
|
|
gc_unlock();
|
|
|
|
|
|
|
|
// using gc_realloc to resize to 0, which means free the memory
|
2018-07-28 13:29:47 -04:00
|
|
|
void *p = gc_alloc(4, false, false);
|
2018-03-01 06:49:15 -05:00
|
|
|
mp_printf(&mp_plat_print, "%p\n", gc_realloc(p, 0, false));
|
|
|
|
|
|
|
|
// calling gc_nbytes with a non-heap pointer
|
|
|
|
mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL));
|
|
|
|
}
|
|
|
|
|
2015-05-12 18:34:10 -04:00
|
|
|
// vstr
|
|
|
|
{
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "# vstr\n");
|
2016-10-14 01:46:34 -04:00
|
|
|
vstr_t *vstr = vstr_new(16);
|
2015-05-12 18:34:10 -04:00
|
|
|
vstr_hint_size(vstr, 32);
|
|
|
|
vstr_add_str(vstr, "ts");
|
|
|
|
vstr_ins_byte(vstr, 1, 'e');
|
|
|
|
vstr_ins_char(vstr, 3, 't');
|
|
|
|
vstr_ins_char(vstr, 10, 's');
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
|
2015-05-12 18:34:10 -04:00
|
|
|
|
|
|
|
vstr_cut_head_bytes(vstr, 2);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
|
2015-05-12 18:34:10 -04:00
|
|
|
|
|
|
|
vstr_cut_tail_bytes(vstr, 10);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
|
2015-05-12 18:34:10 -04:00
|
|
|
|
|
|
|
vstr_printf(vstr, "t%cst", 'e');
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
|
2015-05-12 18:34:10 -04:00
|
|
|
|
|
|
|
vstr_cut_out_bytes(vstr, 3, 10);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
|
2015-05-12 18:34:10 -04:00
|
|
|
|
|
|
|
VSTR_FIXED(fix, 4);
|
2017-08-31 18:05:24 -04:00
|
|
|
nlr_buf_t nlr;
|
|
|
|
if (nlr_push(&nlr) == 0) {
|
|
|
|
vstr_add_str(&fix, "large");
|
|
|
|
nlr_pop();
|
|
|
|
} else {
|
|
|
|
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
|
|
|
|
}
|
|
|
|
|
|
|
|
fix.len = fix.alloc;
|
|
|
|
if (nlr_push(&nlr) == 0) {
|
|
|
|
vstr_null_terminated_str(&fix);
|
|
|
|
nlr_pop();
|
|
|
|
} else {
|
|
|
|
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
|
|
|
|
}
|
2015-05-12 18:34:10 -04:00
|
|
|
}
|
|
|
|
|
2015-05-07 19:19:56 -04:00
|
|
|
// repl autocomplete
|
|
|
|
{
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "# repl\n");
|
2015-05-12 18:34:10 -04:00
|
|
|
|
2015-05-07 19:19:56 -04:00
|
|
|
const char *str;
|
2017-07-04 09:44:54 -04:00
|
|
|
size_t len = mp_repl_autocomplete("__n", 3, &mp_plat_print, &str);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
|
2015-05-07 19:19:56 -04:00
|
|
|
|
|
|
|
mp_store_global(MP_QSTR_sys, mp_import_name(MP_QSTR_sys, mp_const_none, MP_OBJ_NEW_SMALL_INT(0)));
|
|
|
|
mp_repl_autocomplete("sys.", 4, &mp_plat_print, &str);
|
|
|
|
len = mp_repl_autocomplete("sys.impl", 8, &mp_plat_print, &str);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
|
2015-05-07 19:19:56 -04:00
|
|
|
}
|
2015-05-08 04:18:38 -04:00
|
|
|
|
2015-05-12 18:34:10 -04:00
|
|
|
// attrtuple
|
|
|
|
{
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "# attrtuple\n");
|
2015-05-12 18:34:10 -04:00
|
|
|
|
|
|
|
static const qstr fields[] = {MP_QSTR_start, MP_QSTR_stop, MP_QSTR_step};
|
|
|
|
static const mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(2), MP_OBJ_NEW_SMALL_INT(3)};
|
|
|
|
mp_obj_print_helper(&mp_plat_print, mp_obj_new_attrtuple(fields, 3, items), PRINT_REPR);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "\n");
|
2015-05-12 18:34:10 -04:00
|
|
|
}
|
|
|
|
|
2015-09-03 18:06:18 -04:00
|
|
|
// str
|
|
|
|
{
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "# str\n");
|
2015-09-03 18:06:18 -04:00
|
|
|
|
|
|
|
// intern string
|
2021-04-22 20:55:39 -04:00
|
|
|
mp_printf(&mp_plat_print, "%d\n", mp_obj_is_qstr(mp_obj_str_intern(mp_obj_new_str("intern me", 9))));
|
2015-09-03 18:06:18 -04:00
|
|
|
}
|
|
|
|
|
2018-02-07 19:14:30 -05:00
|
|
|
// bytearray
|
|
|
|
{
|
|
|
|
mp_printf(&mp_plat_print, "# bytearray\n");
|
|
|
|
|
|
|
|
// create a bytearray via mp_obj_new_bytearray
|
|
|
|
mp_buffer_info_t bufinfo;
|
|
|
|
mp_get_buffer_raise(mp_obj_new_bytearray(4, "data"), &bufinfo, MP_BUFFER_RW);
|
|
|
|
mp_printf(&mp_plat_print, "%.*s\n", bufinfo.len, bufinfo.buf);
|
|
|
|
}
|
|
|
|
|
2015-10-01 13:49:37 -04:00
|
|
|
// mpz
|
|
|
|
{
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "# mpz\n");
|
2015-10-01 13:49:37 -04:00
|
|
|
|
|
|
|
mp_uint_t value;
|
|
|
|
mpz_t mpz;
|
|
|
|
mpz_init_zero(&mpz);
|
|
|
|
|
|
|
|
// mpz_as_uint_checked, with success
|
|
|
|
mpz_set_from_int(&mpz, 12345678);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", (int)value);
|
2015-10-01 13:49:37 -04:00
|
|
|
|
|
|
|
// mpz_as_uint_checked, with negative arg
|
|
|
|
mpz_set_from_int(&mpz, -1);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
|
2015-10-01 13:49:37 -04:00
|
|
|
|
|
|
|
// mpz_as_uint_checked, with overflowing arg
|
|
|
|
mpz_set_from_int(&mpz, 1);
|
|
|
|
mpz_shl_inpl(&mpz, &mpz, 70);
|
2015-10-14 19:23:03 -04:00
|
|
|
mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
|
2018-02-25 07:43:16 -05:00
|
|
|
|
|
|
|
// mpz_set_from_float with inf as argument
|
|
|
|
mpz_set_from_float(&mpz, 1.0 / 0.0);
|
|
|
|
mpz_as_uint_checked(&mpz, &value);
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", (int)value);
|
|
|
|
|
|
|
|
// mpz_set_from_float with 0 as argument
|
|
|
|
mpz_set_from_float(&mpz, 0);
|
|
|
|
mpz_as_uint_checked(&mpz, &value);
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", (int)value);
|
|
|
|
|
|
|
|
// mpz_set_from_float with 0<x<1 as argument
|
|
|
|
mpz_set_from_float(&mpz, 1e-10);
|
|
|
|
mpz_as_uint_checked(&mpz, &value);
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", (int)value);
|
|
|
|
|
|
|
|
// mpz_set_from_float with 1<=x<2 as argument
|
|
|
|
mpz_set_from_float(&mpz, 1.5);
|
|
|
|
mpz_as_uint_checked(&mpz, &value);
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", (int)value);
|
|
|
|
|
|
|
|
// mpz_set_from_float with 2<x as argument
|
|
|
|
mpz_set_from_float(&mpz, 12345);
|
|
|
|
mpz_as_uint_checked(&mpz, &value);
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", (int)value);
|
|
|
|
|
|
|
|
// mpz_mul_inpl with dest==rhs, lhs!=rhs
|
|
|
|
mpz_t mpz2;
|
|
|
|
mpz_set_from_int(&mpz, 2);
|
|
|
|
mpz_init_from_int(&mpz2, 3);
|
|
|
|
mpz_mul_inpl(&mpz, &mpz2, &mpz);
|
|
|
|
mpz_as_uint_checked(&mpz, &value);
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", (int)value);
|
2015-10-01 13:49:37 -04:00
|
|
|
}
|
|
|
|
|
2016-12-29 02:07:38 -05:00
|
|
|
// runtime utils
|
|
|
|
{
|
|
|
|
mp_printf(&mp_plat_print, "# runtime utils\n");
|
|
|
|
|
|
|
|
// call mp_call_function_1_protected
|
|
|
|
mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), MP_OBJ_NEW_SMALL_INT(1));
|
|
|
|
// call mp_call_function_1_protected with invalid args
|
2017-11-15 21:17:51 -05:00
|
|
|
mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), mp_obj_new_str("abc", 3));
|
2016-12-29 02:07:38 -05:00
|
|
|
|
|
|
|
// call mp_call_function_2_protected
|
|
|
|
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));
|
|
|
|
// call mp_call_function_2_protected with invalid args
|
2017-11-15 21:17:51 -05:00
|
|
|
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));
|
2016-12-29 02:07:38 -05:00
|
|
|
}
|
|
|
|
|
2017-01-03 22:23:29 -05:00
|
|
|
// warning
|
|
|
|
{
|
|
|
|
mp_emitter_warning(MP_PASS_CODE_SIZE, "test");
|
|
|
|
}
|
|
|
|
|
2017-01-04 19:12:05 -05:00
|
|
|
// format float
|
|
|
|
{
|
|
|
|
mp_printf(&mp_plat_print, "# format float\n");
|
|
|
|
|
|
|
|
// format with inadequate buffer size
|
|
|
|
char buf[5];
|
|
|
|
mp_format_float(1, buf, sizeof(buf), 'g', 0, '+');
|
|
|
|
mp_printf(&mp_plat_print, "%s\n", buf);
|
|
|
|
|
|
|
|
// format with just enough buffer so that precision must be
|
|
|
|
// set from 0 to 1 twice
|
|
|
|
char buf2[8];
|
|
|
|
mp_format_float(1, buf2, sizeof(buf2), 'g', 0, '+');
|
|
|
|
mp_printf(&mp_plat_print, "%s\n", buf2);
|
|
|
|
|
|
|
|
// format where precision is trimmed to avoid buffer overflow
|
|
|
|
mp_format_float(1, buf2, sizeof(buf2), 'e', 0, '+');
|
|
|
|
mp_printf(&mp_plat_print, "%s\n", buf2);
|
|
|
|
}
|
|
|
|
|
2017-03-14 02:58:43 -04:00
|
|
|
// binary
|
|
|
|
{
|
|
|
|
mp_printf(&mp_plat_print, "# binary\n");
|
|
|
|
|
|
|
|
// call function with float and double typecodes
|
|
|
|
float far[1];
|
|
|
|
double dar[1];
|
|
|
|
mp_binary_set_val_array_from_int('f', far, 0, 123);
|
|
|
|
mp_printf(&mp_plat_print, "%.0f\n", (double)far[0]);
|
|
|
|
mp_binary_set_val_array_from_int('d', dar, 0, 456);
|
|
|
|
mp_printf(&mp_plat_print, "%.0lf\n", dar[0]);
|
|
|
|
}
|
|
|
|
|
2018-02-27 00:17:10 -05:00
|
|
|
// VM
|
|
|
|
{
|
|
|
|
mp_printf(&mp_plat_print, "# VM\n");
|
|
|
|
|
|
|
|
// call mp_execute_bytecode with invalide bytecode (should raise NotImplementedError)
|
|
|
|
mp_obj_fun_bc_t fun_bc;
|
2021-03-15 09:57:36 -04:00
|
|
|
fun_bc.bytecode = (const byte *)"\x01"; // just needed for n_state
|
2018-02-27 00:17:10 -05:00
|
|
|
mp_code_state_t *code_state = m_new_obj_var(mp_code_state_t, mp_obj_t, 1);
|
|
|
|
code_state->fun_bc = &fun_bc;
|
2021-03-15 09:57:36 -04:00
|
|
|
code_state->ip = (const byte *)"\x00"; // just needed for an invalid opcode
|
2018-02-27 00:17:10 -05:00
|
|
|
code_state->sp = &code_state->state[0];
|
2021-04-23 15:26:42 -04:00
|
|
|
code_state->exc_sp_idx = 0;
|
2018-02-27 00:17:10 -05:00
|
|
|
code_state->old_globals = NULL;
|
|
|
|
mp_vm_return_kind_t ret = mp_execute_bytecode(code_state, MP_OBJ_NULL);
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError);
|
|
|
|
}
|
|
|
|
|
2017-03-16 03:05:33 -04:00
|
|
|
// scheduler
|
|
|
|
{
|
|
|
|
mp_printf(&mp_plat_print, "# scheduler\n");
|
|
|
|
|
|
|
|
// lock scheduler
|
|
|
|
mp_sched_lock();
|
|
|
|
|
|
|
|
// schedule multiple callbacks; last one should fail
|
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// test nested locking/unlocking
|
|
|
|
mp_sched_lock();
|
|
|
|
mp_sched_unlock();
|
|
|
|
|
|
|
|
// shouldn't do anything while scheduler is locked
|
|
|
|
mp_handle_pending();
|
|
|
|
|
|
|
|
// unlock scheduler
|
|
|
|
mp_sched_unlock();
|
|
|
|
mp_printf(&mp_plat_print, "unlocked\n");
|
|
|
|
|
|
|
|
// drain pending callbacks
|
|
|
|
while (mp_sched_num_pending()) {
|
|
|
|
mp_handle_pending();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-23 15:26:42 -04:00
|
|
|
// ringbuf
|
|
|
|
{
|
|
|
|
byte buf[100];
|
|
|
|
ringbuf_t ringbuf = {buf, sizeof(buf), 0, 0};
|
|
|
|
|
|
|
|
mp_printf(&mp_plat_print, "# ringbuf\n");
|
|
|
|
|
|
|
|
// Single-byte put/get with empty ringbuf.
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
ringbuf_put(&ringbuf, 22);
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_get(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
|
|
|
|
// Two-byte put/get with empty ringbuf.
|
|
|
|
ringbuf_put16(&ringbuf, 0xaa55);
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
|
|
|
|
// Two-byte put with full ringbuf.
|
|
|
|
for (int i = 0; i < 99; ++i) {
|
|
|
|
ringbuf_put(&ringbuf, i);
|
|
|
|
}
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb));
|
|
|
|
// Two-byte put with one byte free.
|
|
|
|
ringbuf_get(&ringbuf);
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x3377));
|
|
|
|
ringbuf_get(&ringbuf);
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0xcc99));
|
|
|
|
for (int i = 0; i < 97; ++i) {
|
|
|
|
ringbuf_get(&ringbuf);
|
|
|
|
}
|
|
|
|
mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
|
|
|
|
mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf));
|
|
|
|
|
|
|
|
// Two-byte put with wrap around on first byte:
|
|
|
|
ringbuf.iput = 0;
|
|
|
|
ringbuf.iget = 0;
|
|
|
|
for (int i = 0; i < 99; ++i) {
|
|
|
|
ringbuf_put(&ringbuf, i);
|
|
|
|
ringbuf_get(&ringbuf);
|
|
|
|
}
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb));
|
|
|
|
mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
|
|
|
|
|
|
|
|
// Two-byte put with wrap around on second byte:
|
|
|
|
ringbuf.iput = 0;
|
|
|
|
ringbuf.iget = 0;
|
|
|
|
for (int i = 0; i < 98; ++i) {
|
|
|
|
ringbuf_put(&ringbuf, i);
|
|
|
|
ringbuf_get(&ringbuf);
|
|
|
|
}
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x22ff));
|
|
|
|
mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
|
|
|
|
|
|
|
|
// Two-byte get from empty ringbuf.
|
|
|
|
ringbuf.iput = 0;
|
|
|
|
ringbuf.iget = 0;
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf));
|
|
|
|
|
|
|
|
// Two-byte get from ringbuf with one byte available.
|
|
|
|
ringbuf.iput = 0;
|
|
|
|
ringbuf.iget = 0;
|
|
|
|
ringbuf_put(&ringbuf, 0xaa);
|
|
|
|
mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf));
|
|
|
|
}
|
|
|
|
|
2017-01-15 23:04:53 -05:00
|
|
|
mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t);
|
|
|
|
s->base.type = &mp_type_stest_fileio;
|
|
|
|
s->buf = NULL;
|
|
|
|
s->len = 0;
|
|
|
|
s->pos = 0;
|
|
|
|
s->error_code = 0;
|
|
|
|
mp_obj_streamtest_t *s2 = m_new_obj(mp_obj_streamtest_t);
|
|
|
|
s2->base.type = &mp_type_stest_textio2;
|
|
|
|
|
2016-09-02 01:07:42 -04:00
|
|
|
// return a tuple of data for testing on the Python side
|
2017-01-15 23:04:53 -05:00
|
|
|
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)};
|
2016-09-02 01:07:42 -04:00
|
|
|
return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items);
|
2015-05-07 19:19:56 -04:00
|
|
|
}
|
2015-05-08 04:18:38 -04:00
|
|
|
MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage);
|
2015-05-07 19:19:56 -04:00
|
|
|
|
|
|
|
#endif
|