Skip to content

Commit 8d01bd3

Browse files
flowergrassdpgeorge
authored andcommitted
tests: Improve stream.c test coverage.
1 parent b82fc8d commit 8d01bd3

3 files changed

Lines changed: 178 additions & 3 deletions

File tree

tests/unix/extra_coverage.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,46 @@
55
import sys
66
sys.exit()
77

8+
import uerrno
9+
810
data = extra_coverage()
911

1012
# test hashing of str/bytes that have an invalid hash
11-
print(data)
13+
print(data[0], data[1])
1214
print(hash(data[0]))
1315
print(hash(data[1]))
1416
print(hash(bytes(data[0], 'utf8')))
1517
print(hash(str(data[1], 'utf8')))
1618

19+
# test streams
20+
stream = data[2] # has set_error and set_buf. Write always returns error
21+
stream.set_error(uerrno.EAGAIN) # non-blocking error
22+
print(stream.read()) # read all encounters non-blocking error
23+
print(stream.read(1)) # read 1 byte encounters non-blocking error
24+
print(stream.readline()) # readline encounters non-blocking error
25+
print(stream.readinto(bytearray(10))) # readinto encounters non-blocking error
26+
print(stream.write(b'1')) # write encounters non-blocking error
27+
print(stream.write1(b'1')) # write1 encounters non-blocking error
28+
stream.set_buf(b'123')
29+
print(stream.read(4)) # read encounters non-blocking error after successful reads
30+
stream.set_buf(b'123')
31+
print(stream.read1(4)) # read1 encounters non-blocking error after successful reads
32+
stream.set_buf(b'123')
33+
print(stream.readline(4)) # readline encounters non-blocking error after successful reads
34+
try:
35+
print(stream.ioctl(0, 0)) # ioctl encounters non-blocking error; raises OSError
36+
except OSError:
37+
print('OSError')
38+
stream.set_error(0)
39+
print(stream.ioctl(0, bytearray(10))) # successful ioctl call
40+
41+
stream2 = data[3] # is textio and sets .write = NULL
42+
try:
43+
print(stream2.write(b'1')) # attempt to call NULL implementation
44+
except OSError:
45+
print('OSError')
46+
print(stream2.read(1)) # read 1 byte encounters non-blocking error with textio stream
47+
1748
# test basic import of frozen scripts
1849
import frzstr1
1950
import frzmpy1

tests/unix/extra_coverage.py.exp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,24 @@ Warning: test
4343
?
4444
+1e+00
4545
+1e+00
46-
('0123456789', b'0123456789')
46+
0123456789 b'0123456789'
4747
7300
4848
7300
4949
7300
5050
7300
51+
None
52+
None
53+
None
54+
None
55+
None
56+
None
57+
b'123'
58+
b'123'
59+
b'123'
60+
OSError
61+
0
62+
OSError
63+
None
5164
frzstr1
5265
frzmpy1
5366
frzstr_pkg1.__init__

unix/coverage.c

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <stdio.h>
2+
#include <string.h>
23

34
#include "py/obj.h"
45
#include "py/objstr.h"
@@ -8,6 +9,127 @@
89
#include "py/builtin.h"
910
#include "py/emit.h"
1011
#include "py/formatfloat.h"
12+
#include "py/stream.h"
13+
14+
// stream testing object
15+
typedef struct _mp_obj_streamtest_t {
16+
mp_obj_base_t base;
17+
uint8_t *buf;
18+
size_t len;
19+
size_t pos;
20+
int error_code;
21+
} mp_obj_streamtest_t;
22+
23+
STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) {
24+
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
25+
mp_buffer_info_t bufinfo;
26+
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
27+
o->buf = m_new(uint8_t, bufinfo.len);
28+
memcpy(o->buf, bufinfo.buf, bufinfo.len);
29+
o->len = bufinfo.len;
30+
o->pos = 0;
31+
return mp_const_none;
32+
}
33+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf);
34+
35+
STATIC mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) {
36+
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
37+
o->error_code = mp_obj_get_int(err_in);
38+
return mp_const_none;
39+
}
40+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error);
41+
42+
STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
43+
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
44+
if (o->pos < o->len) {
45+
if (size > o->len - o->pos) {
46+
size = o->len - o->pos;
47+
}
48+
memcpy(buf, o->buf + o->pos, size);
49+
o->pos += size;
50+
return size;
51+
} else if (o->error_code == 0) {
52+
return 0;
53+
} else {
54+
*errcode = o->error_code;
55+
return MP_STREAM_ERROR;
56+
}
57+
}
58+
59+
STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
60+
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
61+
(void)buf;
62+
(void)size;
63+
*errcode = o->error_code;
64+
return MP_STREAM_ERROR;
65+
}
66+
67+
STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
68+
mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
69+
(void)arg;
70+
(void)request;
71+
(void)errcode;
72+
if (o->error_code != 0) {
73+
*errcode = o->error_code;
74+
return MP_STREAM_ERROR;
75+
}
76+
return 0;
77+
}
78+
79+
STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
80+
{ MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) },
81+
{ MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) },
82+
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
83+
{ MP_ROM_QSTR(MP_QSTR_read1), MP_ROM_PTR(&mp_stream_read1_obj) },
84+
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
85+
{ MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) },
86+
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
87+
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
88+
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
89+
};
90+
91+
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
92+
93+
STATIC const mp_stream_p_t fileio_stream_p = {
94+
.read = stest_read,
95+
.write = stest_write,
96+
.ioctl = stest_ioctl,
97+
};
98+
99+
STATIC const mp_obj_type_t mp_type_stest_fileio = {
100+
{ &mp_type_type },
101+
.protocol = &fileio_stream_p,
102+
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
103+
};
104+
105+
// stream read returns non-blocking error
106+
STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
107+
(void)o_in;
108+
(void)buf;
109+
(void)size;
110+
*errcode = MP_EAGAIN;
111+
return MP_STREAM_ERROR;
112+
}
113+
114+
STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = {
115+
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
116+
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
117+
};
118+
119+
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2);
120+
121+
STATIC const mp_stream_p_t textio_stream_p2 = {
122+
.read = stest_read2,
123+
.write = NULL,
124+
.is_text = true,
125+
};
126+
127+
STATIC const mp_obj_type_t mp_type_stest_textio2 = {
128+
{ &mp_type_type },
129+
.protocol = &textio_stream_p2,
130+
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict2,
131+
};
132+
11133

12134
#if defined(MICROPY_UNIX_COVERAGE)
13135

@@ -157,8 +279,17 @@ STATIC mp_obj_t extra_coverage(void) {
157279
mp_printf(&mp_plat_print, "%s\n", buf2);
158280
}
159281

282+
mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t);
283+
s->base.type = &mp_type_stest_fileio;
284+
s->buf = NULL;
285+
s->len = 0;
286+
s->pos = 0;
287+
s->error_code = 0;
288+
mp_obj_streamtest_t *s2 = m_new_obj(mp_obj_streamtest_t);
289+
s2->base.type = &mp_type_stest_textio2;
290+
160291
// return a tuple of data for testing on the Python side
161-
mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj};
292+
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)};
162293
return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items);
163294
}
164295
MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage);

0 commit comments

Comments
 (0)