Skip to content

Commit a11155c

Browse files
committed
tests/encode: add streaming encode coverage
- Add STREAMING=1 variants for test1_suit, test2_simple, test3_corner_cases, and test4_senml. - Exercise streaming encode paths via stream_write helpers and cbor_stream_encode_* entrypoints.
1 parent 62309f3 commit a11155c

13 files changed

Lines changed: 508 additions & 3 deletions

File tree

tests/encode/test1_suit/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ set(py_command
2323
${bit_arg}
2424
)
2525

26+
if (STREAMING)
27+
list(APPEND py_command --stream-encode)
28+
endif()
29+
2630
execute_process(
2731
COMMAND ${py_command}
2832
COMMAND_ERROR_IS_FATAL ANY

tests/encode/test1_suit/src/main.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,70 @@
99
#include "manifest3_encode.h"
1010
#include "zcbor_print.h"
1111

12+
#ifdef STREAMING
13+
#include <string.h>
14+
15+
struct stream_ctx {
16+
uint8_t *buf;
17+
size_t size;
18+
size_t pos;
19+
};
20+
21+
static size_t stream_write(void *user_data, const uint8_t *data, size_t len)
22+
{
23+
struct stream_ctx *ctx = (struct stream_ctx *)user_data;
24+
25+
if (!ctx || !data) {
26+
return 0;
27+
}
28+
if (len == 0) {
29+
return 0;
30+
}
31+
if (ctx->pos + len > ctx->size) {
32+
return 0;
33+
}
34+
35+
memcpy(&ctx->buf[ctx->pos], data, len);
36+
ctx->pos += len;
37+
return len;
38+
}
39+
40+
static int stream_encode_SUIT_Command_Sequence(uint8_t *payload, size_t payload_len,
41+
const struct SUIT_Command_Sequence *input, size_t *out_len)
42+
{
43+
struct stream_ctx ctx = {
44+
.buf = payload,
45+
.size = payload_len,
46+
.pos = 0,
47+
};
48+
int rc = cbor_stream_encode_SUIT_Command_Sequence(stream_write, &ctx, input, NULL, out_len);
49+
50+
if (rc == ZCBOR_SUCCESS) {
51+
zassert_equal(*out_len, ctx.pos, NULL);
52+
}
53+
return rc;
54+
}
55+
56+
static int stream_encode_SUIT_Outer_Wrapper(uint8_t *payload, size_t payload_len,
57+
const struct SUIT_Outer_Wrapper *input, size_t *out_len)
58+
{
59+
struct stream_ctx ctx = {
60+
.buf = payload,
61+
.size = payload_len,
62+
.pos = 0,
63+
};
64+
int rc = cbor_stream_encode_SUIT_Outer_Wrapper(stream_write, &ctx, input, NULL, out_len);
65+
66+
if (rc == ZCBOR_SUCCESS) {
67+
zassert_equal(*out_len, ctx.pos, NULL);
68+
}
69+
return rc;
70+
}
71+
72+
#define cbor_encode_SUIT_Command_Sequence stream_encode_SUIT_Command_Sequence
73+
#define cbor_encode_SUIT_Outer_Wrapper stream_encode_SUIT_Outer_Wrapper
74+
#endif /* STREAMING */
75+
1276
/* draft-ietf-suit-manifest-02 Example 0 */
1377
uint8_t test_vector0_02[] = {
1478
0xa2, 0x01, 0x58, 0x54, 0xd2, 0x84, 0x43, 0xa1, 0x01,

tests/encode/test1_suit/testcase.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,12 @@ tests:
77
- qemu_malta/qemu_malta/be
88
tags: zcbor encode canonical test1
99
extra_args: CANONICAL=CANONICAL
10+
11+
zcbor.encode.test1_suit.streaming_canonical:
12+
platform_allow:
13+
- native_sim
14+
- native_sim/native/64
15+
- mps2/an521/cpu0
16+
- qemu_malta/qemu_malta/be
17+
tags: zcbor encode streaming canonical test1
18+
extra_args: STREAMING=1 CANONICAL=CANONICAL

tests/encode/test2_simple/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ set(py_command
2222
--file-header ${CMAKE_CURRENT_LIST_DIR}/file_header_copyright.txt
2323
)
2424

25+
if (STREAMING)
26+
zephyr_compile_definitions(STREAMING)
27+
list(APPEND py_command --stream-encode)
28+
endif()
29+
2530
execute_process(
2631
COMMAND ${py_command}
2732
COMMAND_ERROR_IS_FATAL ANY
@@ -31,4 +36,3 @@ include(${PROJECT_BINARY_DIR}/pet.cmake)
3136

3237
target_link_libraries(pet PRIVATE zephyr_interface)
3338
target_link_libraries(app PRIVATE pet)
34-

tests/encode/test2_simple/src/main.c

Lines changed: 185 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,86 @@
88
#include <pet_encode.h>
99
#include <zcbor_encode.h>
1010

11-
#ifndef ZCBOR_CANONICAL
11+
#if !defined(ZCBOR_CANONICAL) || defined(STREAMING)
1212
#define TEST_INDEFINITE_LENGTH_ARRAYS
1313
#endif
1414
#include <common_test.h>
1515

16+
#ifdef STREAMING
17+
#include <string.h>
18+
#include <errno.h>
19+
20+
struct stream_ctx {
21+
uint8_t *buf;
22+
size_t size;
23+
size_t pos;
24+
};
25+
26+
static size_t stream_write(void *user_data, const uint8_t *data, size_t len)
27+
{
28+
struct stream_ctx *ctx = (struct stream_ctx *)user_data;
29+
30+
if (!ctx) {
31+
return 0;
32+
}
33+
if (len == 0) {
34+
return 0;
35+
}
36+
if (!data) {
37+
return 0;
38+
}
39+
if (ctx->pos + len > ctx->size) {
40+
return 0;
41+
}
42+
43+
memcpy(&ctx->buf[ctx->pos], data, len);
44+
ctx->pos += len;
45+
return len;
46+
}
47+
48+
struct bstr_push_ctx {
49+
const uint8_t *data;
50+
size_t len;
51+
};
52+
53+
static bool bstr_push(void *user_data, zcbor_state_t *state)
54+
{
55+
struct bstr_push_ctx *ctx = (struct bstr_push_ctx *)user_data;
56+
57+
if (!ctx) {
58+
return false;
59+
}
60+
61+
return zcbor_bstr_encode_chunk(state, ctx->data, ctx->len);
62+
}
63+
#endif /* STREAMING */
64+
65+
#ifdef STREAMING
66+
struct bstr_chunk_ctx {
67+
int idx;
68+
const uint8_t *chunks[2];
69+
size_t lens[2];
70+
};
71+
72+
static int bstr_next_chunk(void *user_ctx, const uint8_t **ptr, size_t *len)
73+
{
74+
struct bstr_chunk_ctx *c = (struct bstr_chunk_ctx *)user_ctx;
75+
76+
if (!c || !ptr || !len) {
77+
return -EINVAL;
78+
}
79+
80+
if (c->idx >= 2) {
81+
return 0;
82+
}
83+
84+
*ptr = c->chunks[c->idx];
85+
*len = c->lens[c->idx];
86+
c->idx++;
87+
return 1;
88+
}
89+
#endif /* STREAMING */
90+
1691

1792
/* This test uses generated code to encode a 'Pet' instance. It populates the
1893
* generated struct, and runs the generated encoding function, then checks that
@@ -41,12 +116,51 @@ ZTEST(cbor_encode_test2, test_pet)
41116
size_t out_len;
42117

43118
/* Check that encoding succeeded. */
119+
#ifdef STREAMING
120+
struct stream_ctx ctx = {
121+
.buf = output,
122+
.size = sizeof(output),
123+
.pos = 0,
124+
};
125+
126+
struct bstr_push_ctx push_ctx = {
127+
.data = pet.birthday.value,
128+
.len = pet.birthday.len,
129+
};
130+
struct cbor_stream_io_Pet io = { 0 };
131+
132+
io.chunks_out_Timestamp.ctx = &push_ctx;
133+
io.chunks_out_Timestamp.call = bstr_push;
134+
135+
int rc = cbor_stream_encode_Pet(stream_write, &ctx, &pet, NULL, &out_len);
136+
zassert_equal(ZCBOR_SUCCESS, rc, NULL);
137+
zassert_equal(out_len, ctx.pos, NULL);
138+
#else
44139
zassert_equal(ZCBOR_SUCCESS, cbor_encode_Pet(output, sizeof(output), &pet, &out_len), NULL);
140+
#endif
45141

46142
/* Check that the resulting length is correct. */
47143
zassert_equal(sizeof(exp_output), out_len, NULL);
48144
/* Check the payload contents. */
49145
zassert_mem_equal(exp_output, output, sizeof(exp_output), NULL);
146+
147+
#ifdef STREAMING
148+
const uint8_t *exp_output_push = exp_output;
149+
size_t exp_output_push_len = sizeof(exp_output);
150+
uint8_t output_push[32];
151+
struct stream_ctx push_out_ctx = {
152+
.buf = output_push,
153+
.size = sizeof(output_push),
154+
.pos = 0,
155+
};
156+
size_t out_len_push;
157+
158+
rc = cbor_stream_encode_Pet(stream_write, &push_out_ctx, &pet, &io, &out_len_push);
159+
zassert_equal(ZCBOR_SUCCESS, rc, NULL);
160+
zassert_equal(out_len_push, push_out_ctx.pos, NULL);
161+
zassert_equal(exp_output_push_len, out_len_push, NULL);
162+
zassert_mem_equal(exp_output_push, output_push, exp_output_push_len, NULL);
163+
#endif
50164
}
51165

52166

@@ -59,7 +173,18 @@ ZTEST(cbor_encode_test2, test_pet)
59173
ZTEST(cbor_encode_test2, test_pet_raw)
60174
{
61175
uint8_t payload[100] = {0};
176+
#ifdef STREAMING
177+
struct stream_ctx ctx = {
178+
.buf = payload,
179+
.size = sizeof(payload),
180+
.pos = 0,
181+
};
182+
zcbor_state_t states[4];
183+
zcbor_new_encode_state_streaming(states, 4, stream_write, &ctx, 1);
184+
zcbor_state_t *state = states;
185+
#else
62186
ZCBOR_STATE_E(state, 4, payload, sizeof(payload), 1);
187+
#endif
63188

64189
uint8_t exp_output[] = {
65190
LIST(3),
@@ -97,10 +222,69 @@ ZTEST(cbor_encode_test2, test_pet_raw)
97222
/* Check that encoding succeeded. */
98223
zassert_true(res, NULL);
99224
/* Check that the resulting length is correct. */
225+
#ifdef STREAMING
226+
zassert_equal(sizeof(exp_output), ctx.pos, "%d != %d\r\n",
227+
sizeof(exp_output), ctx.pos);
228+
#else
100229
zassert_equal(sizeof(exp_output), state->payload - payload, "%d != %d\r\n",
101230
sizeof(exp_output), state->payload - payload);
231+
#endif
102232
/* Check the payload contents. */
103233
zassert_mem_equal(exp_output, payload, sizeof(exp_output), NULL);
104234
}
105235

236+
#ifdef STREAMING
237+
ZTEST(cbor_encode_test2, test_bstr_indefinite_chunks)
238+
{
239+
/* Expect: 0x5f (bstr indefinite), 0x43 01 02 03, 0x42 04 05, 0xff (break) */
240+
uint8_t output[16];
241+
struct stream_ctx ctx = {
242+
.buf = output,
243+
.size = sizeof(output),
244+
.pos = 0,
245+
};
246+
247+
const uint8_t c1[] = { 0x01, 0x02, 0x03 };
248+
const uint8_t c2[] = { 0x04, 0x05 };
249+
struct bstr_chunk_ctx chunks = {
250+
.idx = 0,
251+
.chunks = { c1, c2 },
252+
.lens = { sizeof(c1), sizeof(c2) },
253+
};
254+
255+
zcbor_state_t s[4];
256+
zcbor_new_encode_state_streaming(s, 4, stream_write, &ctx, 1);
257+
258+
zassert_true(zcbor_bstr_encode_indefinite_chunks(s, bstr_next_chunk, &chunks), NULL);
259+
zassert_equal(ctx.pos, 1 + 1 + sizeof(c1) + 1 + sizeof(c2) + 1, NULL);
260+
261+
const uint8_t exp[] = { 0x5f, 0x43, 0x01, 0x02, 0x03, 0x42, 0x04, 0x05, 0xff };
262+
zassert_mem_equal(output, exp, ctx.pos, NULL);
263+
}
264+
#endif /* STREAMING */
265+
266+
#ifdef STREAMING
267+
ZTEST(cbor_encode_test2, test_streaming_container_headers)
268+
{
269+
/* In streaming mode, lists/maps must be indefinite-length (0x9f/0xbf ... 0xff). */
270+
uint8_t output[32];
271+
struct stream_ctx ctx = {
272+
.buf = output,
273+
.size = sizeof(output),
274+
.pos = 0,
275+
};
276+
277+
zcbor_state_t s[4];
278+
zcbor_new_encode_state_streaming(s, 4, stream_write, &ctx, 1);
279+
280+
zassert_true(zcbor_list_start_encode(s, 3), NULL);
281+
zassert_true(zcbor_uint32_put(s, 1), NULL);
282+
zassert_true(zcbor_list_end_encode(s, 3), NULL);
283+
284+
zassert_true(ctx.pos >= 2, NULL);
285+
zassert_equal(output[0], 0x9f, NULL);
286+
zassert_equal(output[ctx.pos - 1], 0xff, NULL);
287+
}
288+
#endif /* STREAMING */
289+
106290
ZTEST_SUITE(cbor_encode_test2, NULL, NULL, NULL, NULL, NULL);

tests/encode/test2_simple/testcase.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@ tests:
66
- mps2/an521/cpu0
77
- qemu_malta/qemu_malta/be
88
tags: zcbor encode test
9+
10+
zcbor.encode.test2_simple.streaming:
11+
platform_allow:
12+
- native_sim
13+
- native_sim/native/64
14+
- mps2/an521/cpu0
15+
- qemu_malta/qemu_malta/be
16+
tags: zcbor encode streaming test
17+
extra_args: STREAMING=1
18+
19+
20+
zcbor.encode.test2_simple.streaming_canonical:
21+
platform_allow:
22+
- native_sim
23+
- native_sim/native/64
24+
- mps2/an521/cpu0
25+
- qemu_malta/qemu_malta/be
26+
tags: zcbor encode streaming canonical test
27+
extra_args: STREAMING=1 CANONICAL=CANONICAL
28+
29+
930
zcbor.encode.test2_simple.canonical:
1031
platform_allow:
1132
- native_sim

tests/encode/test3_corner_cases/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ set(py_command
5959
--short-names
6060
)
6161

62+
if (STREAMING)
63+
list(APPEND py_command --stream-encode)
64+
endif()
65+
6266
execute_process(
6367
COMMAND ${py_command}
6468
COMMAND_ERROR_IS_FATAL ANY

0 commit comments

Comments
 (0)