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)
59173ZTEST (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+
106290ZTEST_SUITE (cbor_encode_test2 , NULL , NULL , NULL , NULL , NULL );
0 commit comments