LexLeo 0.0.0-dev+f8e5087-dirty
Technical documentation
Loading...
Searching...
No Matches
unit_test_dynamic_buffer_stream.c
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-3.0-or-later
2 * Copyright (C) 2026 Sylvain Labopin
3 */
4
47
50
51#include "osal/mem/osal_mem.h"
53
54// for white-box tests
57
61
62#include "lexleo_cmocka.h"
63
81{
82 (void)state;
83
85
86 assert_true(ret.default_cap > 0);
87}
88
112{
113 (void)state;
114
115 const osal_mem_ops_t *dummy_mem_p =
116 (const osal_mem_ops_t *)(uintptr_t)0x1234u;
117
118 const stream_env_t dummy_port_env = {0};
119 const stream_env_t *dummy_port_env_p = &dummy_port_env;
120
122 dynamic_buffer_stream_default_env(dummy_mem_p, dummy_port_env_p);
123
124 assert_ptr_equal(ret.mem, dummy_mem_p);
125 assert_memory_equal(&ret.port_env, dummy_port_env_p, sizeof(ret.port_env));
126}
127
195
214typedef enum {
215 OUT_CHECK_NONE,
216 OUT_EXPECT_NULL,
217 OUT_EXPECT_NON_NULL,
218 OUT_EXPECT_UNCHANGED
219} out_expect_t;
220
228typedef struct {
229 const char *name;
230
231 // arrange
233 size_t fail_call_idx; // 0 = no OOM, otherwise 1-based
234
235 // assert
236 stream_status_t expected_ret;
237 out_expect_t out_expect;
238} test_dynamic_buffer_stream_create_stream_case_t;
239
249typedef struct {
250 // runtime resources
251 stream_t *out;
252
253 // injection
255
257
258 const test_dynamic_buffer_stream_create_stream_case_t *tc;
259} test_dynamic_buffer_stream_create_stream_fixture_t;
260
261//-----------------------------------------------------------------------------
262// FIXTURES
263//-----------------------------------------------------------------------------
264
269static int setup_dynamic_buffer_stream_create_stream(void **state)
270{
271 const test_dynamic_buffer_stream_create_stream_case_t *tc =
272 (const test_dynamic_buffer_stream_create_stream_case_t *)(*state);
273
274 test_dynamic_buffer_stream_create_stream_fixture_t *fx =
275 (test_dynamic_buffer_stream_create_stream_fixture_t *)malloc(sizeof(*fx));
276 if (!fx) return -1;
277
278 osal_memset(fx, 0, sizeof(*fx));
279 fx->tc = tc;
280
281 fake_memory_reset();
283 && tc->fail_call_idx > 0) {
284 fake_memory_fail_only_on_call(tc->fail_call_idx);
285 }
286
287 // DI
288 fx->env.mem = osal_mem_test_fake_ops();
289 fx->env.port_env.mem = osal_mem_test_fake_ops();
290
291 fx->cfg.default_cap = 16;
292
293 *state = fx;
294 return 0;
295}
296
301static int teardown_dynamic_buffer_stream_create_stream(void **state)
302{
303 test_dynamic_buffer_stream_create_stream_fixture_t *fx =
304 (test_dynamic_buffer_stream_create_stream_fixture_t *)(*state);
305
306 if (fx->out) {
307 stream_destroy(&fx->out);
308 fx->out = NULL;
309 }
310
311 assert_true(fake_memory_no_leak());
312 assert_true(fake_memory_no_invalid_free());
313 assert_true(fake_memory_no_double_free());
314
315 free(fx);
316 return 0;
317}
318
319//-----------------------------------------------------------------------------
320// TEST
321//-----------------------------------------------------------------------------
322
327static void test_dynamic_buffer_stream_create_stream(void **state)
328{
329 test_dynamic_buffer_stream_create_stream_fixture_t *fx =
330 (test_dynamic_buffer_stream_create_stream_fixture_t *)(*state);
331 const test_dynamic_buffer_stream_create_stream_case_t *tc = fx->tc;
332
333 // ARRANGE
336
337 stream_t **out_arg = &fx->out;
338 const dynamic_buffer_stream_cfg_t *cfg_arg = &fx->cfg;
339 const dynamic_buffer_stream_env_t *env_arg = &fx->env;
340
341 // invalid args
342 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_OUT_NULL) out_arg = NULL;
343 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_CFG_NULL) cfg_arg = NULL;
344 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_ENV_NULL) env_arg = NULL;
345
346 // ensure OUT_EXPECT_UNCHANGED is meaningful
347 if (tc->out_expect == OUT_EXPECT_UNCHANGED && out_arg != NULL) {
348 fx->out = (stream_t *)(uintptr_t)0xDEADC0DEu; // sentinel
349 }
350
351 stream_t *out_arg_snapshot = fx->out;
352
353 // ACT
354 ret = dynamic_buffer_stream_create_stream(out_arg, cfg_arg, env_arg);
355
356 // ASSERT
357 assert_int_equal(ret, tc->expected_ret);
358
359 switch (tc->out_expect) {
360 case OUT_CHECK_NONE: break;
361 case OUT_EXPECT_NULL: assert_null(fx->out); break;
362 case OUT_EXPECT_NON_NULL: assert_non_null(fx->out); break;
363 case OUT_EXPECT_UNCHANGED:
364 assert_ptr_equal(out_arg_snapshot, fx->out);
365 fx->out = NULL; // prevent teardown from destroying sentinel
366 break;
367 default: assert_true(false);
368 }
369
371 assert_non_null(fx->out);
372
373 const char msg[] = "hello";
374 size_t w = stream_write(fx->out, msg, sizeof(msg) - 1, &st);
375 assert_int_equal((int)w, (int)(sizeof(msg) - 1));
376 assert_true(st == STREAM_STATUS_OK);
377
378 assert_int_equal(stream_flush(fx->out), STREAM_STATUS_OK);
379 }
380}
381
382//-----------------------------------------------------------------------------
383// CASES
384//-----------------------------------------------------------------------------
385
386static const test_dynamic_buffer_stream_create_stream_case_t
387CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_OK = {
388 .name = "dynamic_buffer_stream_create_stream_ok",
390 .fail_call_idx = 0,
391
392 .expected_ret = STREAM_STATUS_OK,
393 .out_expect = OUT_EXPECT_NON_NULL
394};
395
396static const test_dynamic_buffer_stream_create_stream_case_t
397CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_OUT_NULL = {
398 .name = "dynamic_buffer_stream_create_stream_out_null",
400 .fail_call_idx = 0,
401
402 .expected_ret = STREAM_STATUS_INVALID,
403 .out_expect = OUT_CHECK_NONE
404};
405
406static const test_dynamic_buffer_stream_create_stream_case_t
407CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_CFG_NULL = {
408 .name = "dynamic_buffer_stream_create_stream_cfg_null",
410 .fail_call_idx = 0,
411
412 .expected_ret = STREAM_STATUS_INVALID,
413 .out_expect = OUT_EXPECT_UNCHANGED
414};
415
416static const test_dynamic_buffer_stream_create_stream_case_t
417CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_ENV_NULL = {
418 .name = "dynamic_buffer_stream_create_stream_env_null",
420 .fail_call_idx = 0,
421
422 .expected_ret = STREAM_STATUS_INVALID,
423 .out_expect = OUT_EXPECT_UNCHANGED
424};
425
426static const test_dynamic_buffer_stream_create_stream_case_t
427CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_OOM = {
428 .name = "dynamic_buffer_stream_create_stream_oom",
430 .fail_call_idx = 1,
431
432 .expected_ret = STREAM_STATUS_OOM,
433 .out_expect = OUT_EXPECT_UNCHANGED
434};
435
436//-----------------------------------------------------------------------------
437// CASES REGISTRY
438//-----------------------------------------------------------------------------
439
440#define DYNAMIC_BUFFER_STREAM_CREATE_STREAM_CASES(X) \
441X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_OK) \
442X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_OUT_NULL) \
443X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_CFG_NULL) \
444X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_ENV_NULL) \
445X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_STREAM_OOM)
446
447#define DYNAMIC_BUFFER_STREAM_MAKE_CREATE_STREAM_TEST(case_sym) \
448LEXLEO_MAKE_TEST(dynamic_buffer_stream_create_stream, case_sym)
449
450static const struct CMUnitTest dynamic_buffer_stream_create_stream_tests[] = {
451 DYNAMIC_BUFFER_STREAM_CREATE_STREAM_CASES(
452 DYNAMIC_BUFFER_STREAM_MAKE_CREATE_STREAM_TEST)
453};
454
455#undef DYNAMIC_BUFFER_STREAM_CREATE_STREAM_CASES
456#undef DYNAMIC_BUFFER_STREAM_MAKE_CREATE_STREAM_TEST
457
567
573typedef enum {
574 DESC_CHECK_NONE,
575 DESC_EXPECT_EMPTY,
576 DESC_EXPECT_VALID
577} desc_expect_t;
578
586typedef struct {
587 const char *name;
588
589 // arrange
591 size_t fail_call_idx; // 0 = no OOM, otherwise 1-based
592
593 // assert
594 stream_status_t expected_ret;
595 desc_expect_t desc_expect;
596} test_dynamic_buffer_stream_create_desc_case_t;
597
608typedef struct {
609 // runtime resources
611
612 // injection
614 const osal_mem_ops_t *mem;
615
616 stream_key_t key;
618
619 const test_dynamic_buffer_stream_create_desc_case_t *tc;
620} test_dynamic_buffer_stream_create_desc_fixture_t;
621
622//-----------------------------------------------------------------------------
623// FIXTURES
624//-----------------------------------------------------------------------------
625
630static int setup_dynamic_buffer_stream_create_desc(void **state)
631{
632 const test_dynamic_buffer_stream_create_desc_case_t *tc =
633 (const test_dynamic_buffer_stream_create_desc_case_t *)(*state);
634
635 test_dynamic_buffer_stream_create_desc_fixture_t *fx =
636 (test_dynamic_buffer_stream_create_desc_fixture_t *)malloc(sizeof(*fx));
637 if (!fx) return -1;
638
639 osal_memset(fx, 0, sizeof(*fx));
640 fx->tc = tc;
641
642 fake_memory_reset();
644 && tc->fail_call_idx > 0) {
645 fake_memory_fail_only_on_call(tc->fail_call_idx);
646 }
647
648 // DI
649 fx->env.mem = osal_mem_test_fake_ops();
650 fx->env.port_env.mem = osal_mem_test_fake_ops();
651 fx->mem = osal_mem_test_fake_ops();
652
653 fx->key = "dynamic_buffer";
654
655 fx->cfg.default_cap = 16u;
656
657 *state = fx;
658 return 0;
659}
660
665static int teardown_dynamic_buffer_stream_create_desc(void **state)
666{
667 test_dynamic_buffer_stream_create_desc_fixture_t *fx =
668 (test_dynamic_buffer_stream_create_desc_fixture_t *)(*state);
669
670 if (fx->out.ud_dtor) fx->out.ud_dtor(fx->out.ud, fx->mem);
671
672 assert_true(fake_memory_no_leak());
673 assert_true(fake_memory_no_invalid_free());
674 assert_true(fake_memory_no_double_free());
675
676 free(fx);
677 return 0;
678}
679
680//-----------------------------------------------------------------------------
681// TEST
682//-----------------------------------------------------------------------------
683
688static void test_dynamic_buffer_stream_create_desc(void **state)
689{
690 test_dynamic_buffer_stream_create_desc_fixture_t *fx =
691 (test_dynamic_buffer_stream_create_desc_fixture_t *)(*state);
692 const test_dynamic_buffer_stream_create_desc_case_t *tc = fx->tc;
693
694 // ARRANGE
696
697 stream_adapter_desc_t *out_arg = &fx->out;
698 stream_key_t key_arg = fx->key;
699 const dynamic_buffer_stream_cfg_t *cfg_arg = &fx->cfg;
700 const dynamic_buffer_stream_env_t *env_arg = &fx->env;
701 const osal_mem_ops_t *mem_arg = fx->mem;
702
703 // invalid args
704 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_OUT_NULL) out_arg = NULL;
705 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_KEY_NULL) key_arg = NULL;
706 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_KEY_EMPTY) key_arg = "";
707 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_CFG_NULL) cfg_arg = NULL;
708 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_ENV_NULL) env_arg = NULL;
709 if (tc->scenario == DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_MEM_NULL) mem_arg = NULL;
710
711 if (tc->desc_expect == DESC_EXPECT_EMPTY && out_arg != NULL) {
712 fx->out.key = (stream_key_t)(uintptr_t)0xDEADC0DEu;
713 fx->out.ctor = (void *)(uintptr_t)0xDEADC0DEu;
714 fx->out.ud = (void *)(uintptr_t)0xDEADC0DEu;
715 fx->out.ud_dtor = (void *)(uintptr_t)0xDEADC0DEu;
716 }
717
718 // ACT
719 ret = dynamic_buffer_stream_create_desc(out_arg, key_arg, cfg_arg, env_arg, mem_arg);
720
721 // ASSERT
722 assert_int_equal(ret, tc->expected_ret);
723
724 if (tc->desc_expect == DESC_EXPECT_EMPTY) {
725 assert_null(fx->out.key);
726 assert_null(fx->out.ctor);
727 assert_null(fx->out.ud);
728 assert_null(fx->out.ud_dtor);
729 }
730 else if (tc->desc_expect == DESC_EXPECT_VALID) {
731 assert_true(fx->out.key != (stream_key_t)(uintptr_t)0xDEADC0DEu);
732 assert_non_null(fx->out.key);
733 assert_true(*fx->out.key != '\0');
734 assert_true(fx->out.ctor != (void *)(uintptr_t)0xDEADC0DEu);
735 assert_non_null(fx->out.ctor);
736 assert_true(fx->out.ud != (void *)(uintptr_t)0xDEADC0DEu);
737 assert_non_null(fx->out.ud);
738 assert_true(fx->out.ud_dtor != (void *)(uintptr_t)0xDEADC0DEu);
739 assert_non_null(fx->out.ud_dtor);
740 }
741 else {
742 assert_true(tc->desc_expect == DESC_CHECK_NONE);
743 }
744}
745
746//-----------------------------------------------------------------------------
747// CASES
748//-----------------------------------------------------------------------------
749
750static const test_dynamic_buffer_stream_create_desc_case_t
751CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_OK = {
752 .name = "dynamic_buffer_stream_create_desc_ok",
754 .fail_call_idx = 0,
755
756 .expected_ret = STREAM_STATUS_OK,
757 .desc_expect = DESC_EXPECT_VALID
758};
759
760static const test_dynamic_buffer_stream_create_desc_case_t
761CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_OUT_NULL = {
762 .name = "dynamic_buffer_stream_create_desc_out_null",
764 .fail_call_idx = 0,
765
766 .expected_ret = STREAM_STATUS_INVALID,
767 .desc_expect = DESC_CHECK_NONE
768};
769
770static const test_dynamic_buffer_stream_create_desc_case_t
771CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_KEY_NULL = {
772 .name = "dynamic_buffer_stream_create_desc_key_null",
774 .fail_call_idx = 0,
775
776 .expected_ret = STREAM_STATUS_INVALID,
777 .desc_expect = DESC_EXPECT_EMPTY
778};
779
780static const test_dynamic_buffer_stream_create_desc_case_t
781CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_KEY_EMPTY = {
782 .name = "dynamic_buffer_stream_create_desc_key_empty",
784 .fail_call_idx = 0,
785
786 .expected_ret = STREAM_STATUS_INVALID,
787 .desc_expect = DESC_EXPECT_EMPTY
788};
789
790static const test_dynamic_buffer_stream_create_desc_case_t
791CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_CFG_NULL = {
792 .name = "dynamic_buffer_stream_create_desc_cfg_null",
794 .fail_call_idx = 0,
795
796 .expected_ret = STREAM_STATUS_INVALID,
797 .desc_expect = DESC_EXPECT_EMPTY
798};
799
800static const test_dynamic_buffer_stream_create_desc_case_t
801CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_ENV_NULL = {
802 .name = "dynamic_buffer_stream_create_desc_env_null",
804 .fail_call_idx = 0,
805
806 .expected_ret = STREAM_STATUS_INVALID,
807 .desc_expect = DESC_EXPECT_EMPTY
808};
809
810static const test_dynamic_buffer_stream_create_desc_case_t
811CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_MEM_NULL = {
812 .name = "dynamic_buffer_stream_create_desc_mem_null",
814 .fail_call_idx = 0,
815
816 .expected_ret = STREAM_STATUS_INVALID,
817 .desc_expect = DESC_EXPECT_EMPTY
818};
819
820static const test_dynamic_buffer_stream_create_desc_case_t
821CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_OOM_1 = {
822 .name = "dynamic_buffer_stream_create_desc_oom_1",
824 .fail_call_idx = 1,
825
826 .expected_ret = STREAM_STATUS_OOM,
827 .desc_expect = DESC_EXPECT_EMPTY
828};
829
830//-----------------------------------------------------------------------------
831// CASES REGISTRY
832//-----------------------------------------------------------------------------
833
834#define DYNAMIC_BUFFER_STREAM_CREATE_DESC_CASES(X) \
835X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_OK) \
836X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_OUT_NULL) \
837X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_KEY_NULL) \
838X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_KEY_EMPTY) \
839X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_CFG_NULL) \
840X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_ENV_NULL) \
841X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_MEM_NULL) \
842X(CASE_DYNAMIC_BUFFER_STREAM_CREATE_DESC_OOM_1)
843
844#define DYNAMIC_BUFFER_STREAM_MAKE_CREATE_DESC_TEST(case_sym) \
845LEXLEO_MAKE_TEST(dynamic_buffer_stream_create_desc, case_sym)
846
847static const struct CMUnitTest create_desc_dynamic_buffer_stream_tests[] = {
848 DYNAMIC_BUFFER_STREAM_CREATE_DESC_CASES(
849 DYNAMIC_BUFFER_STREAM_MAKE_CREATE_DESC_TEST)
850};
851
852#undef DYNAMIC_BUFFER_STREAM_CREATE_DESC_CASES
853#undef DYNAMIC_BUFFER_STREAM_MAKE_CREATE_DESC_TEST
854
986
1000typedef struct {
1001 const char *name;
1002
1003 // arrange
1005 size_t initial_cap;
1006 size_t prefill_len;
1007 size_t prefill_read_pos;
1008 size_t write_len;
1009 size_t fail_call_idx; // 0 = no injected OOM, otherwise 1-based
1010
1011 // assert
1012 size_t expected_written;
1013 stream_status_t expected_st;
1014 bool expect_cap_growth;
1015 bool expect_backend_unchanged;
1016} test_dynamic_buffer_stream_write_case_t;
1017
1027typedef struct {
1028 // runtime resources
1029 stream_t *s;
1030
1031 // injection
1034
1035 // test payload
1036 uint8_t payload[64];
1037
1038 const test_dynamic_buffer_stream_write_case_t *tc;
1039} test_dynamic_buffer_stream_write_fixture_t;
1040
1041//-----------------------------------------------------------------------------
1042// FIXTURES
1043//-----------------------------------------------------------------------------
1044
1049static int setup_dynamic_buffer_stream_write(void **state)
1050{
1051 const test_dynamic_buffer_stream_write_case_t *tc =
1052 (const test_dynamic_buffer_stream_write_case_t *)(*state);
1053
1054 test_dynamic_buffer_stream_write_fixture_t *fx =
1055 (test_dynamic_buffer_stream_write_fixture_t *)malloc(sizeof(*fx));
1056 if (!fx) return -1;
1057
1058 osal_memset(fx, 0, sizeof(*fx));
1059 fx->tc = tc;
1060
1061 fake_memory_reset();
1062
1063 // DI
1064 fx->env.mem = osal_mem_test_fake_ops();
1065 fx->env.port_env.mem = osal_mem_test_fake_ops();
1066
1067 fx->cfg.default_cap = tc->initial_cap;
1068
1069 for (size_t i = 0; i < sizeof(fx->payload); ++i) {
1070 fx->payload[i] = (uint8_t)('A' + (i % 26));
1071 }
1072
1073 if (dynamic_buffer_stream_create_stream(&fx->s, &fx->cfg, &fx->env) != STREAM_STATUS_OK) {
1074 free(fx);
1075 return -1;
1076 }
1077
1078 /*
1079 * Inject OOM after creation so the first subsequent allocation performed by
1080 * growth/reserve fails.
1081 */
1083 && tc->fail_call_idx > 0) {
1084 fake_memory_fail_only_on_call(tc->fail_call_idx);
1085 }
1086
1087 *state = fx;
1088 return 0;
1089}
1090
1095static int teardown_dynamic_buffer_stream_write(void **state)
1096{
1097 test_dynamic_buffer_stream_write_fixture_t *fx =
1098 (test_dynamic_buffer_stream_write_fixture_t *)(*state);
1099
1100 if (fx->s) {
1101 stream_destroy(&fx->s);
1102 fx->s = NULL;
1103 }
1104
1105 assert_true(fake_memory_no_leak());
1106 assert_true(fake_memory_no_invalid_free());
1107 assert_true(fake_memory_no_double_free());
1108
1109 free(fx);
1110 return 0;
1111}
1112
1113//-----------------------------------------------------------------------------
1114// TEST
1115//-----------------------------------------------------------------------------
1116
1125static void test_dynamic_buffer_stream_write(void **state)
1126{
1127 test_dynamic_buffer_stream_write_fixture_t *fx =
1128 (test_dynamic_buffer_stream_write_fixture_t *)(*state);
1129 const test_dynamic_buffer_stream_write_case_t *tc = fx->tc;
1130
1131 // ARRANGE
1133
1134 stream_t *s = fx->s;
1135 assert_non_null(s);
1136 assert_non_null(s->backend);
1137
1139 assert_non_null(dbs);
1140
1141 dynamic_buffer_t *dbuf = &dbs->state.dbuf;
1142 assert_non_null(dbuf);
1143
1144 /*
1145 * Seed backend state.
1146 *
1147 * Backend fields used here:
1148 * - buf
1149 * - len
1150 * - cap
1151 * - read_pos
1152 */
1153 assert_true(tc->prefill_len <= tc->initial_cap);
1154 if (tc->prefill_len > 0) {
1155 assert_non_null(dbuf->buf);
1156 osal_memcpy(dbuf->buf, fx->payload, tc->prefill_len);
1157 }
1158 dbuf->len = tc->prefill_len;
1159 dbuf->read_pos = tc->prefill_read_pos;
1160
1162 dbuf->len = SIZE_MAX;
1163 dbuf->read_pos = tc->prefill_read_pos;
1164 }
1165
1166 const void *buf_arg = fx->payload;
1167 size_t n_arg = tc->write_len;
1168
1170 buf_arg = NULL;
1171 n_arg = 0;
1172 }
1174 buf_arg = NULL;
1175 }
1177 n_arg = 0;
1178 }
1179
1180 // Snapshot backend state for failure / invariance assertions.
1181 uint8_t before_bytes[64];
1182 const size_t snap_n =
1183 (dbuf->len < sizeof(before_bytes)) ? dbuf->len : sizeof(before_bytes);
1184 if (snap_n > 0 && dbuf->buf) {
1185 osal_memcpy(before_bytes, dbuf->buf, snap_n);
1186 }
1187
1188 const void *buf_snapshot = dbuf->buf;
1189 const size_t len_snapshot = dbuf->len;
1190 const size_t cap_snapshot = dbuf->cap;
1191 const size_t read_pos_snapshot = dbuf->read_pos;
1192
1193 // ACT
1194 size_t written = stream_write(s, buf_arg, n_arg, &st);
1195
1196 // ASSERT
1197 assert_int_equal((int)written, (int)tc->expected_written);
1198 assert_int_equal((int)st, (int)tc->expected_st);
1199
1200 if (tc->expect_backend_unchanged) {
1201 assert_ptr_equal(dbuf->buf, buf_snapshot);
1202 assert_int_equal((int)dbuf->len, (int)len_snapshot);
1203 assert_int_equal((int)dbuf->cap, (int)cap_snapshot);
1204 assert_int_equal((int)dbuf->read_pos, (int)read_pos_snapshot);
1205
1206 if (snap_n > 0 && dbuf->buf) {
1207 assert_memory_equal(dbuf->buf, before_bytes, snap_n);
1208 }
1209 return;
1210 }
1211
1212 // Success paths.
1213 assert_int_equal((int)dbuf->read_pos, (int)read_pos_snapshot);
1214 assert_int_equal((int)dbuf->len, (int)(len_snapshot + tc->write_len));
1215
1216 if (tc->expect_cap_growth) {
1217 assert_true(dbuf->cap > cap_snapshot);
1218 }
1219 else {
1220 assert_true(dbuf->cap >= cap_snapshot);
1221 }
1222
1223 if (len_snapshot > 0) {
1224 assert_memory_equal(dbuf->buf, before_bytes, snap_n);
1225 }
1226 if (tc->write_len > 0) {
1227 assert_memory_equal(
1228 (uint8_t *)dbuf->buf + len_snapshot,
1229 fx->payload,
1230 tc->write_len);
1231 }
1232}
1233
1234//-----------------------------------------------------------------------------
1235// CASES
1236//-----------------------------------------------------------------------------
1237
1238static const test_dynamic_buffer_stream_write_case_t
1239CASE_DYNAMIC_BUFFER_STREAM_WRITE_OK_NO_GROW = {
1240 .name = "dynamic_buffer_stream_write_ok_no_grow",
1242 .initial_cap = 16u,
1243 .prefill_len = 3u,
1244 .prefill_read_pos = 1u,
1245 .write_len = 5u,
1246 .fail_call_idx = 0u,
1247
1248 .expected_written = 5u,
1249 .expected_st = STREAM_STATUS_OK,
1250 .expect_cap_growth = false,
1251 .expect_backend_unchanged = false
1252};
1253
1254static const test_dynamic_buffer_stream_write_case_t
1255CASE_DYNAMIC_BUFFER_STREAM_WRITE_ZERO_LEN = {
1256 .name = "dynamic_buffer_stream_write_zero_len",
1258 .initial_cap = 16u,
1259 .prefill_len = 3u,
1260 .prefill_read_pos = 1u,
1261 .write_len = 0u,
1262 .fail_call_idx = 0u,
1263
1264 .expected_written = 0u,
1265 .expected_st = STREAM_STATUS_OK,
1266 .expect_cap_growth = false,
1267 .expect_backend_unchanged = true
1268};
1269
1270static const test_dynamic_buffer_stream_write_case_t
1271CASE_DYNAMIC_BUFFER_STREAM_WRITE_BUF_NULL_ZERO_LEN = {
1272 .name = "dynamic_buffer_stream_write_buf_null_zero_len",
1274 .initial_cap = 16u,
1275 .prefill_len = 3u,
1276 .prefill_read_pos = 1u,
1277 .write_len = 0u,
1278 .fail_call_idx = 0u,
1279
1280 .expected_written = 0u,
1281 .expected_st = STREAM_STATUS_OK,
1282 .expect_cap_growth = false,
1283 .expect_backend_unchanged = true
1284};
1285
1286static const test_dynamic_buffer_stream_write_case_t
1287CASE_DYNAMIC_BUFFER_STREAM_WRITE_OK_GROW = {
1288 .name = "dynamic_buffer_stream_write_ok_grow",
1290 .initial_cap = 4u,
1291 .prefill_len = 4u,
1292 .prefill_read_pos = 2u,
1293 .write_len = 5u,
1294 .fail_call_idx = 0u,
1295
1296 .expected_written = 5u,
1297 .expected_st = STREAM_STATUS_OK,
1298 .expect_cap_growth = true,
1299 .expect_backend_unchanged = false
1300};
1301
1302static const test_dynamic_buffer_stream_write_case_t
1303CASE_DYNAMIC_BUFFER_STREAM_WRITE_BUF_NULL_NONZERO = {
1304 .name = "dynamic_buffer_stream_write_buf_null_nonzero",
1306 .initial_cap = 16u,
1307 .prefill_len = 3u,
1308 .prefill_read_pos = 1u,
1309 .write_len = 5u,
1310 .fail_call_idx = 0u,
1311
1312 .expected_written = 0u,
1313 .expected_st = STREAM_STATUS_INVALID,
1314 .expect_cap_growth = false,
1315 .expect_backend_unchanged = true
1316};
1317
1318static const test_dynamic_buffer_stream_write_case_t
1319CASE_DYNAMIC_BUFFER_STREAM_WRITE_RESERVE_OOM = {
1320 .name = "dynamic_buffer_stream_write_reserve_oom",
1322 .initial_cap = 4u,
1323 .prefill_len = 4u,
1324 .prefill_read_pos = 2u,
1325 .write_len = 5u,
1326 .fail_call_idx = 1u,
1327
1328 .expected_written = 0u,
1329 .expected_st = STREAM_STATUS_OOM,
1330 .expect_cap_growth = false,
1331 .expect_backend_unchanged = true
1332};
1333
1334static const test_dynamic_buffer_stream_write_case_t
1335CASE_DYNAMIC_BUFFER_STREAM_WRITE_SIZE_OVERFLOW = {
1336 .name = "dynamic_buffer_stream_write_size_overflow",
1338 .initial_cap = 16u,
1339 .prefill_len = 0u,
1340 .prefill_read_pos = 0u,
1341 .write_len = 1u,
1342 .fail_call_idx = 0u,
1343
1344 .expected_written = 0u,
1345 .expected_st = STREAM_STATUS_INVALID,
1346 .expect_cap_growth = false,
1347 .expect_backend_unchanged = true
1348};
1349
1350//-----------------------------------------------------------------------------
1351// CASES REGISTRY
1352//-----------------------------------------------------------------------------
1353
1354#define DYNAMIC_BUFFER_STREAM_WRITE_CASES(X) \
1355X(CASE_DYNAMIC_BUFFER_STREAM_WRITE_OK_NO_GROW) \
1356X(CASE_DYNAMIC_BUFFER_STREAM_WRITE_ZERO_LEN) \
1357X(CASE_DYNAMIC_BUFFER_STREAM_WRITE_BUF_NULL_ZERO_LEN) \
1358X(CASE_DYNAMIC_BUFFER_STREAM_WRITE_OK_GROW) \
1359X(CASE_DYNAMIC_BUFFER_STREAM_WRITE_BUF_NULL_NONZERO) \
1360X(CASE_DYNAMIC_BUFFER_STREAM_WRITE_RESERVE_OOM) \
1361X(CASE_DYNAMIC_BUFFER_STREAM_WRITE_SIZE_OVERFLOW)
1362
1363#define DYNAMIC_BUFFER_STREAM_MAKE_WRITE_TEST(case_sym) \
1364LEXLEO_MAKE_TEST(dynamic_buffer_stream_write, case_sym)
1365
1366static const struct CMUnitTest dynamic_buffer_stream_write_tests[] = {
1367 DYNAMIC_BUFFER_STREAM_WRITE_CASES(DYNAMIC_BUFFER_STREAM_MAKE_WRITE_TEST)
1368};
1369
1370#undef DYNAMIC_BUFFER_STREAM_WRITE_CASES
1371#undef DYNAMIC_BUFFER_STREAM_MAKE_WRITE_TEST
1372
1487
1499typedef struct {
1500 const char *name;
1501
1502 // arrange
1504 size_t initial_cap;
1505 size_t prefill_len;
1506 size_t prefill_read_pos;
1507 size_t read_len;
1508
1509 // assert
1510 size_t expected_read;
1511 stream_status_t expected_st;
1512 bool expect_backend_unchanged;
1513} test_dynamic_buffer_stream_read_case_t;
1514
1525typedef struct {
1526 // runtime resources
1527 stream_t *s;
1528
1529 // injection
1532
1533 // test buffers
1534 uint8_t payload[64];
1535 uint8_t read_buf[64];
1536
1537 const test_dynamic_buffer_stream_read_case_t *tc;
1538} test_dynamic_buffer_stream_read_fixture_t;
1539
1540//-----------------------------------------------------------------------------
1541// FIXTURES
1542//-----------------------------------------------------------------------------
1543
1548static int setup_dynamic_buffer_stream_read(void **state)
1549{
1550 const test_dynamic_buffer_stream_read_case_t *tc =
1551 (const test_dynamic_buffer_stream_read_case_t *)(*state);
1552
1553 test_dynamic_buffer_stream_read_fixture_t *fx =
1554 (test_dynamic_buffer_stream_read_fixture_t *)malloc(sizeof(*fx));
1555 if (!fx) return -1;
1556
1557 osal_memset(fx, 0, sizeof(*fx));
1558 fx->tc = tc;
1559
1560 fake_memory_reset();
1561
1562 // DI
1563 fx->env.mem = osal_mem_test_fake_ops();
1564 fx->env.port_env.mem = osal_mem_test_fake_ops();
1565
1566 fx->cfg.default_cap = tc->initial_cap;
1567
1568 for (size_t i = 0; i < sizeof(fx->payload); ++i) {
1569 fx->payload[i] = (uint8_t)('A' + (i % 26));
1570 }
1571 for (size_t i = 0; i < sizeof(fx->read_buf); ++i) {
1572 fx->read_buf[i] = (uint8_t)0xCDu;
1573 }
1574
1575 if (dynamic_buffer_stream_create_stream(&fx->s, &fx->cfg, &fx->env)
1576 != STREAM_STATUS_OK) {
1577 free(fx);
1578 return -1;
1579 }
1580
1581 *state = fx;
1582 return 0;
1583}
1584
1589static int teardown_dynamic_buffer_stream_read(void **state)
1590{
1591 test_dynamic_buffer_stream_read_fixture_t *fx =
1592 (test_dynamic_buffer_stream_read_fixture_t *)(*state);
1593
1594 if (fx->s) {
1595 stream_destroy(&fx->s);
1596 fx->s = NULL;
1597 }
1598
1599 assert_true(fake_memory_no_leak());
1600 assert_true(fake_memory_no_invalid_free());
1601 assert_true(fake_memory_no_double_free());
1602
1603 free(fx);
1604 return 0;
1605}
1606
1607//-----------------------------------------------------------------------------
1608// TEST
1609//-----------------------------------------------------------------------------
1610
1620static void test_dynamic_buffer_stream_read(void **state)
1621{
1622 test_dynamic_buffer_stream_read_fixture_t *fx =
1623 (test_dynamic_buffer_stream_read_fixture_t *)(*state);
1624 const test_dynamic_buffer_stream_read_case_t *tc = fx->tc;
1625
1626 // ARRANGE
1628
1629 stream_t *s = fx->s;
1630 assert_non_null(s);
1631 assert_non_null(s->backend);
1632
1634 assert_non_null(dbs);
1635
1636 dynamic_buffer_t *dbuf = &dbs->state.dbuf;
1637 assert_non_null(dbuf);
1638
1639 /*
1640 * Seed backend state.
1641 *
1642 * Backend fields used here:
1643 * - buf
1644 * - len
1645 * - cap
1646 * - read_pos
1647 */
1648 assert_true(tc->prefill_len <= dbuf->cap);
1649 if (tc->prefill_len > 0) {
1650 assert_non_null(dbuf->buf);
1651 osal_memcpy(dbuf->buf, fx->payload, tc->prefill_len);
1652 }
1653 dbuf->len = tc->prefill_len;
1654 dbuf->read_pos = tc->prefill_read_pos;
1655
1656 void *buf_arg = fx->read_buf;
1657 size_t n_arg = tc->read_len;
1658
1660 buf_arg = NULL;
1661 n_arg = 0u;
1662 }
1664 buf_arg = NULL;
1665 }
1667 n_arg = 0u;
1668 }
1669
1670 const size_t unread_before =
1671 (dbuf->read_pos < dbuf->len) ? (dbuf->len - dbuf->read_pos) : 0u;
1672 const size_t expected_copy =
1673 (tc->read_len < unread_before) ? tc->read_len : unread_before;
1674
1675 uint8_t before_bytes[64];
1676 const size_t snap_n =
1677 (dbuf->len < sizeof(before_bytes)) ? dbuf->len : sizeof(before_bytes);
1678 if (snap_n > 0 && dbuf->buf) {
1679 osal_memcpy(before_bytes, dbuf->buf, snap_n);
1680 }
1681
1682 uint8_t read_buf_snapshot[64];
1683 osal_memcpy(read_buf_snapshot, fx->read_buf, sizeof(read_buf_snapshot));
1684
1685 const void *buf_snapshot = dbuf->buf;
1686 const size_t len_snapshot = dbuf->len;
1687 const size_t cap_snapshot = dbuf->cap;
1688 const size_t read_pos_snapshot = dbuf->read_pos;
1689
1690 // ACT
1691 size_t rd = stream_read(s, buf_arg, n_arg, &st);
1692
1693 // ASSERT
1694 assert_int_equal((int)rd, (int)tc->expected_read);
1695 assert_int_equal((int)st, (int)tc->expected_st);
1696
1697 if (tc->expect_backend_unchanged) {
1698 assert_ptr_equal(dbuf->buf, buf_snapshot);
1699 assert_int_equal((int)dbuf->len, (int)len_snapshot);
1700 assert_int_equal((int)dbuf->cap, (int)cap_snapshot);
1701 assert_int_equal((int)dbuf->read_pos, (int)read_pos_snapshot);
1702
1703 if (snap_n > 0 && dbuf->buf) {
1704 assert_memory_equal(dbuf->buf, before_bytes, snap_n);
1705 }
1706
1707 if (buf_arg != NULL) {
1708 assert_memory_equal(fx->read_buf, read_buf_snapshot, sizeof(fx->read_buf));
1709 }
1710 return;
1711 }
1712
1713 // Success paths with data consumption.
1714 assert_ptr_equal(dbuf->buf, buf_snapshot);
1715 assert_int_equal((int)dbuf->len, (int)len_snapshot);
1716 assert_int_equal((int)dbuf->cap, (int)cap_snapshot);
1717 assert_int_equal((int)dbuf->read_pos, (int)(read_pos_snapshot + expected_copy));
1718
1719 if (snap_n > 0 && dbuf->buf) {
1720 assert_memory_equal(dbuf->buf, before_bytes, snap_n);
1721 }
1722
1723 if (expected_copy > 0) {
1724 assert_memory_equal(
1725 fx->read_buf,
1726 fx->payload + read_pos_snapshot,
1727 expected_copy);
1728 }
1729 if (expected_copy < sizeof(fx->read_buf)) {
1730 assert_memory_equal(
1731 fx->read_buf + expected_copy,
1732 read_buf_snapshot + expected_copy,
1733 sizeof(fx->read_buf) - expected_copy);
1734 }
1735}
1736
1737//-----------------------------------------------------------------------------
1738// CASES
1739//-----------------------------------------------------------------------------
1740
1741static const test_dynamic_buffer_stream_read_case_t
1742CASE_DYNAMIC_BUFFER_STREAM_READ_OK_EXACT = {
1743 .name = "dynamic_buffer_stream_read_ok_exact",
1745 .initial_cap = 16u,
1746 .prefill_len = 8u,
1747 .prefill_read_pos = 2u,
1748 .read_len = 3u,
1749
1750 .expected_read = 3u,
1751 .expected_st = STREAM_STATUS_OK,
1752 .expect_backend_unchanged = false
1753};
1754
1755static const test_dynamic_buffer_stream_read_case_t
1756CASE_DYNAMIC_BUFFER_STREAM_READ_OK_CLAMP_TO_AVAILABLE = {
1757 .name = "dynamic_buffer_stream_read_ok_clamp_to_available",
1759 .initial_cap = 16u,
1760 .prefill_len = 8u,
1761 .prefill_read_pos = 6u,
1762 .read_len = 5u,
1763
1764 .expected_read = 2u,
1765 .expected_st = STREAM_STATUS_OK,
1766 .expect_backend_unchanged = false
1767};
1768
1769static const test_dynamic_buffer_stream_read_case_t
1770CASE_DYNAMIC_BUFFER_STREAM_READ_ZERO_LEN = {
1771 .name = "dynamic_buffer_stream_read_zero_len",
1773 .initial_cap = 16u,
1774 .prefill_len = 8u,
1775 .prefill_read_pos = 2u,
1776 .read_len = 0u,
1777
1778 .expected_read = 0u,
1779 .expected_st = STREAM_STATUS_OK,
1780 .expect_backend_unchanged = true
1781};
1782
1783static const test_dynamic_buffer_stream_read_case_t
1784CASE_DYNAMIC_BUFFER_STREAM_READ_BUF_NULL_ZERO_LEN = {
1785 .name = "dynamic_buffer_stream_read_buf_null_zero_len",
1787 .initial_cap = 16u,
1788 .prefill_len = 8u,
1789 .prefill_read_pos = 2u,
1790 .read_len = 0u,
1791
1792 .expected_read = 0u,
1793 .expected_st = STREAM_STATUS_OK,
1794 .expect_backend_unchanged = true
1795};
1796
1797static const test_dynamic_buffer_stream_read_case_t
1798CASE_DYNAMIC_BUFFER_STREAM_READ_BUF_NULL_NONZERO = {
1799 .name = "dynamic_buffer_stream_read_buf_null_nonzero",
1801 .initial_cap = 16u,
1802 .prefill_len = 8u,
1803 .prefill_read_pos = 2u,
1804 .read_len = 3u,
1805
1806 .expected_read = 0u,
1807 .expected_st = STREAM_STATUS_INVALID,
1808 .expect_backend_unchanged = true
1809};
1810
1811static const test_dynamic_buffer_stream_read_case_t
1812CASE_DYNAMIC_BUFFER_STREAM_READ_EOF = {
1813 .name = "dynamic_buffer_stream_read_eof",
1815 .initial_cap = 16u,
1816 .prefill_len = 8u,
1817 .prefill_read_pos = 8u,
1818 .read_len = 3u,
1819
1820 .expected_read = 0u,
1821 .expected_st = STREAM_STATUS_EOF,
1822 .expect_backend_unchanged = true
1823};
1824
1825//-----------------------------------------------------------------------------
1826// CASES REGISTRY
1827//-----------------------------------------------------------------------------
1828
1829#define DYNAMIC_BUFFER_STREAM_READ_CASES(X) \
1830X(CASE_DYNAMIC_BUFFER_STREAM_READ_OK_EXACT) \
1831X(CASE_DYNAMIC_BUFFER_STREAM_READ_OK_CLAMP_TO_AVAILABLE) \
1832X(CASE_DYNAMIC_BUFFER_STREAM_READ_ZERO_LEN) \
1833X(CASE_DYNAMIC_BUFFER_STREAM_READ_BUF_NULL_ZERO_LEN) \
1834X(CASE_DYNAMIC_BUFFER_STREAM_READ_BUF_NULL_NONZERO) \
1835X(CASE_DYNAMIC_BUFFER_STREAM_READ_EOF)
1836
1837#define DYNAMIC_BUFFER_STREAM_MAKE_READ_TEST(case_sym) \
1838LEXLEO_MAKE_TEST(dynamic_buffer_stream_read, case_sym)
1839
1840static const struct CMUnitTest dynamic_buffer_stream_read_tests[] = {
1841 DYNAMIC_BUFFER_STREAM_READ_CASES(DYNAMIC_BUFFER_STREAM_MAKE_READ_TEST)
1842};
1843
1844#undef DYNAMIC_BUFFER_STREAM_READ_CASES
1845#undef DYNAMIC_BUFFER_STREAM_MAKE_READ_TEST
1846
1868static void test_dynamic_buffer_stream_flush(void **state)
1869{
1870 (void)state;
1871
1872 stream_t *s = NULL;
1873
1874 const dynamic_buffer_stream_cfg_t cfg = {
1875 .default_cap = 16u
1876 };
1877
1878 const dynamic_buffer_stream_env_t env = {
1880 .port_env = {
1881 .mem = osal_mem_test_fake_ops()
1882 }
1883 };
1884
1885 assert_int_equal(
1888 assert_non_null(s);
1889 assert_non_null(s->backend);
1890
1892 assert_non_null(dbs);
1893
1894 dynamic_buffer_t *dbuf = &dbs->state.dbuf;
1895 assert_non_null(dbuf);
1896 assert_non_null(dbuf->buf);
1897
1898 osal_memcpy(dbuf->buf, "hello", 5);
1899 dbuf->len = 5u;
1900 dbuf->read_pos = 2u;
1901
1902 char before_bytes[5];
1903 osal_memcpy(before_bytes, dbuf->buf, 5);
1904
1905 const void *buf_snapshot = dbuf->buf;
1906 const size_t len_snapshot = dbuf->len;
1907 const size_t cap_snapshot = dbuf->cap;
1908 const size_t read_pos_snapshot = dbuf->read_pos;
1909
1910 assert_int_equal(stream_flush(s), STREAM_STATUS_OK);
1911
1912 assert_ptr_equal(dbuf->buf, buf_snapshot);
1913 assert_int_equal((int)dbuf->len, (int)len_snapshot);
1914 assert_int_equal((int)dbuf->cap, (int)cap_snapshot);
1915 assert_int_equal((int)dbuf->read_pos, (int)read_pos_snapshot);
1916 assert_memory_equal(dbuf->buf, before_bytes, sizeof(before_bytes));
1917
1918 stream_destroy(&s);
1919 assert_null(s);
1920
1921 assert_true(fake_memory_no_leak());
1922 assert_true(fake_memory_no_invalid_free());
1923 assert_true(fake_memory_no_double_free());
1924}
1925
1946static void test_dynamic_buffer_stream_close(void **state)
1947{
1948 (void)state;
1949
1950 fake_memory_reset();
1951
1952 stream_t *s = NULL;
1953
1954 const dynamic_buffer_stream_cfg_t cfg = {
1955 .default_cap = 16u
1956 };
1957
1958 const dynamic_buffer_stream_env_t env = {
1960 .port_env = {
1961 .mem = osal_mem_test_fake_ops()
1962 }
1963 };
1964
1965 assert_int_equal(
1968 assert_non_null(s);
1969 assert_non_null(s->backend);
1970
1972 assert_non_null(dbs);
1973
1974 dynamic_buffer_t *dbuf = &dbs->state.dbuf;
1975 assert_non_null(dbuf);
1976 assert_non_null(dbuf->buf);
1977
1978 /*
1979 * Seed backend state so destruction exercises a non-trivial backend.
1980 */
1981 osal_memcpy(dbuf->buf, "hello", 5);
1982 dbuf->len = 5u;
1983 dbuf->read_pos = 2u;
1984
1985 /*
1986 * Exercise the private close callback through the public lifecycle API.
1987 */
1988 stream_destroy(&s);
1989
1990 assert_null(s);
1991
1992 assert_true(fake_memory_no_leak());
1993 assert_true(fake_memory_no_invalid_free());
1994 assert_true(fake_memory_no_double_free());
1995}
1996
1999//-----------------------------------------------------------------------------
2000// MAIN
2001//-----------------------------------------------------------------------------
2002
2003int main(void) {
2004 static const struct CMUnitTest dynamic_buffer_stream_stream_non_parametric_tests[] = {
2007 cmocka_unit_test(test_dynamic_buffer_stream_flush),
2008 cmocka_unit_test(test_dynamic_buffer_stream_close),
2009 };
2010
2011 int failed = 0;
2012 failed += cmocka_run_group_tests(dynamic_buffer_stream_stream_non_parametric_tests, NULL, NULL);
2013 failed += cmocka_run_group_tests(dynamic_buffer_stream_create_stream_tests, NULL, NULL);
2014 failed += cmocka_run_group_tests(create_desc_dynamic_buffer_stream_tests, NULL, NULL);
2015 failed += cmocka_run_group_tests(dynamic_buffer_stream_write_tests, NULL, NULL);
2016 failed += cmocka_run_group_tests(dynamic_buffer_stream_read_tests, NULL, NULL);
2017
2018 return failed;
2019}
2020
Composition Root API for the dynamic_buffer_stream adapter.
stream_status_t dynamic_buffer_stream_create_desc(stream_adapter_desc_t *out, stream_key_t key, const dynamic_buffer_stream_cfg_t *cfg, const dynamic_buffer_stream_env_t *env, const osal_mem_ops_t *mem)
Build a stream adapter descriptor for the dynamic_buffer_stream adapter.
stream_status_t dynamic_buffer_stream_create_stream(stream_t **out, const dynamic_buffer_stream_cfg_t *cfg, const dynamic_buffer_stream_env_t *env)
Create a dynamic_buffer_stream instance directly.
dynamic_buffer_stream_cfg_t dynamic_buffer_stream_default_cfg(void)
Return the default configuration for the dynamic_buffer_stream adapter.
dynamic_buffer_stream_env_t dynamic_buffer_stream_default_env(const osal_mem_ops_t *mem, const stream_env_t *port_env)
Return the default injected environment for the dynamic_buffer_stream adapter.
Private backend handle definition for the dynamic_buffer_stream adapter.
int main()
Definition main.c:5
void * osal_memset(void *s, int c, size_t n)
Definition osal_mem.c:30
void * osal_memcpy(void *dest, const void *src, size_t n)
Definition osal_mem.c:25
const osal_mem_ops_t * osal_mem_test_fake_ops(void)
Borrower-facing runtime operations for the stream port.
stream_status_t stream_flush(stream_t *s)
Flush a stream.
Definition stream.c:62
size_t stream_write(stream_t *s, const void *buf, size_t n, stream_status_t *st)
Write bytes to a stream.
Definition stream.c:38
size_t stream_read(stream_t *s, void *buf, size_t n, stream_status_t *st)
Read bytes from a stream.
Definition stream.c:19
Private stream handle definition for the stream port.
const char * stream_key_t
Public identifier type for a registered stream adapter.
Lifecycle services for stream_t handles.
void stream_destroy(stream_t **s)
Destroy a stream handle.
Definition stream.c:98
stream_status_t
Public status codes used by the stream port.
@ STREAM_STATUS_INVALID
@ STREAM_STATUS_EOF
@ STREAM_STATUS_OK
@ STREAM_STATUS_OOM
Configuration type for the dynamic_buffer_stream adapter.
size_t default_cap
Default initial capacity of the internal dynamic buffer.
Injected dependencies for the dynamic_buffer_stream adapter.
const osal_mem_ops_t * mem
Borrowed memory operations table for adapter-owned allocations.
stream_env_t port_env
Borrowed stream port environment.
Private backend handle for the dynamic_buffer_stream adapter.
dynamic_buffer_stream_state_t state
Private dynamic buffer state used by the dynamic_buffer_stream backend.
Public descriptor used to register a concrete stream adapter.
Runtime environment for the stream port.
Definition stream_env.h:35
Private handle structure for a stream_t.
void * backend
static void test_dynamic_buffer_stream_close(void **state)
Test dynamic_buffer_stream_close().
dynamic_buffer_stream_write_scenario_t
Scenarios for dynamic_buffer_stream_write().
@ DYNAMIC_BUFFER_STREAM_WRITE_SCENARIO_RESERVE_OOM
@ DYNAMIC_BUFFER_STREAM_WRITE_SCENARIO_ZERO_LEN
@ DYNAMIC_BUFFER_STREAM_WRITE_SCENARIO_SIZE_OVERFLOW
@ DYNAMIC_BUFFER_STREAM_WRITE_SCENARIO_BUF_NULL_ZERO_LEN
@ DYNAMIC_BUFFER_STREAM_WRITE_SCENARIO_OK_NO_GROW
@ DYNAMIC_BUFFER_STREAM_WRITE_SCENARIO_BUF_NULL_NONZERO
@ DYNAMIC_BUFFER_STREAM_WRITE_SCENARIO_OK_GROW
static void test_dynamic_buffer_stream_flush(void **state)
Test dynamic_buffer_stream_flush().
static void test_dynamic_buffer_stream_default_env(void **state)
Test dynamic_buffer_stream_default_env().
dynamic_buffer_stream_read_scenario_t
Scenarios for dynamic_buffer_stream_read().
@ DYNAMIC_BUFFER_STREAM_READ_SCENARIO_BUF_NULL_NONZERO
@ DYNAMIC_BUFFER_STREAM_READ_SCENARIO_BUF_NULL_ZERO_LEN
@ DYNAMIC_BUFFER_STREAM_READ_SCENARIO_OK_CLAMP_TO_AVAILABLE
@ DYNAMIC_BUFFER_STREAM_READ_SCENARIO_OK_EXACT
@ DYNAMIC_BUFFER_STREAM_READ_SCENARIO_ZERO_LEN
@ DYNAMIC_BUFFER_STREAM_READ_SCENARIO_EOF
dynamic_buffer_stream_create_desc_scenario_t
Scenarios for dynamic_buffer_stream_create_desc().
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_MEM_NULL
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_KEY_NULL
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_ENV_NULL
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_OUT_NULL
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_OK
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_OOM
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_KEY_EMPTY
@ DYNAMIC_BUFFER_STREAM_CREATE_DESC_SCENARIO_CFG_NULL
static void test_dynamic_buffer_stream_default_cfg(void **state)
Test dynamic_buffer_stream_default_cfg().
dynamic_buffer_stream_create_stream_scenario_t
Scenarios for dynamic_buffer_stream_create_stream().
@ DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_CFG_NULL
@ DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_OUT_NULL
@ DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_OOM
@ DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_ENV_NULL
@ DYNAMIC_BUFFER_STREAM_CREATE_STREAM_SCENARIO_OK