ASCII Serial Com
Serial communication library between computers, microcontrollers, FPGAs, etc. Uses only ASCII. Not the most efficient protocol, but meant to be easy to read
Loading...
Searching...
No Matches
test_ascii_serial_com_byte_at_a_time.c
1#include "asc_exception.h"
2#include "ascii_serial_com.h"
3#include "externals/unity.h"
4#include <inttypes.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9size_t input_str_size;
10size_t output_str_size;
11size_t i_input_str;
12size_t i_output_str;
13char input_str[MAXMESSAGELEN + 1];
14char output_str[MAXMESSAGELEN + 1];
15
16void send_out(uint8_t byte);
17uint8_t receive_in(void);
18bool anything_to_receive(void);
19void null_inout_strs(void);
20
21CEXCEPTION_T e1;
22const char *thisMessage;
23
24#define nMessages 12
25const char *messages[nMessages] = {
26 ">xxx.79BD\n",
27 ">000.0FEC\n",
28 ">FFF.FD98\n",
29 ">1234567890ABCDEF.9411\n",
30 ">FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.39DE\n",
31 ">00000000000000000000000000000000000000000.1DC1\n",
32 ">345666666666666666666666666666666666666666666666666666666.C7FB\n",
33 ">00wFFFF.9F3B\n",
34 ">00w.23A6\n",
35 ">abc.C103\n",
36 ">defxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.350F\n",
37 ">AFw0123456789.A86F\n"};
38
39#define nBadMessages 6
40const char *badMessages[nBadMessages] = {
41 ">", "\n", ">\n", ">abc\n", ">abcC103\n",
42 ">abc.C104\n", // bad checksum
43};
44
45void send_out(uint8_t byte) {
46 if (i_output_str < MAXMESSAGELEN) {
47 output_str[i_output_str++] = (char)byte;
48 } else {
49 printf("output_str: %s\n", output_str);
50 TEST_FAIL_MESSAGE(
51 "trying to send message larger than MAXMESSAGELEN using send_out");
52 }
53}
54
55uint8_t receive_in(void) {
56 if (anything_to_receive() && i_input_str < MAXMESSAGELEN) {
57 return (uint8_t)input_str[i_input_str++];
58 } else {
59 printf("input_str: %s\n", input_str);
60 TEST_FAIL_MESSAGE(
61 "trying to receive_in when nothing to receive (problem in test code?)");
62 return 0xFF;
63 }
64}
65
66bool anything_to_receive(void) { return i_input_str < input_str_size; }
67
68void setup_inout_strs(const char *instr) {
69 i_input_str = 0;
70 i_output_str = 0;
71 output_str_size = 0;
72 input_str_size = 0;
73 for (size_t i = 0; i < MAXMESSAGELEN + 1; i++) {
74 input_str[i] = '\0';
75 output_str[i] = '\0';
76 }
77 strncpy(input_str, instr, MAXMESSAGELEN + 1);
78 for (size_t i = 0; i < MAXMESSAGELEN + 1; i++) {
79 if (input_str[i] == '\0')
80 break;
81 input_str_size++;
82 }
83}
84
85void setUp(void) {
86 // set stuff up here
87 setup_inout_strs("");
88}
89
90void tearDown(void) {
91 // clean stuff up here
92}
93
94void test_ascii_serial_com_loopback(void) {
95
96 char ascVersion, appVersion, command, dataBuffer[MAXDATALEN];
97 size_t dataLen;
98
99 Try {
104 size_t iExtraIters = 0;
105
106 for (size_t iMessage = 0; iMessage < nMessages; iMessage++) {
107 setup_inout_strs(messages[iMessage]);
108 while (anything_to_receive() ||
109 !circular_buffer_is_empty_uint8(out_buf) || iExtraIters < 15) {
110 if (anything_to_receive()) {
111 circular_buffer_push_back_uint8(in_buf, receive_in());
112 }
113 if (!circular_buffer_is_empty_uint8(in_buf)) {
115 &asc, &ascVersion, &appVersion, &command, dataBuffer, &dataLen);
116 if (command != '\0') {
118 &asc, ascVersion, appVersion, command, dataBuffer, dataLen);
119 }
120 }
121 if (!circular_buffer_is_empty_uint8(out_buf)) {
122 send_out(circular_buffer_pop_front_uint8(out_buf));
123 }
124 if (!(anything_to_receive() ||
126 iExtraIters++;
127 }
128 // printf("######################################\n");
129 // printf("iExtraIters: %zu\n",iExtraIters);
130 // circular_buffer_print_uint8(in_buf,stdout);
131 // circular_buffer_print_uint8(out_buf,stdout);
132 }
133 // printf("Expected: '%s'\n",messages[iMessage]);
134 // printf("Observed: '%s'\n",output_str);
135 TEST_ASSERT_EQUAL_STRING(messages[iMessage], output_str);
136 }
137 }
138 Catch(e1) {
139 printf("Uncaught exception: %u\n", e1);
140 TEST_FAIL_MESSAGE("Uncaught exception!");
141 }
142}
143
144void test_ascii_serial_com_loopback_random_order(void) {
145
146 char ascVersion, appVersion, command, dataBuffer[MAXDATALEN];
147 size_t dataLen;
148
149 Try {
154 size_t iExtraIters = 0;
155
156 const size_t nTries = 200;
157 for (size_t iTry = 0; iTry < nTries; iTry++) {
158 const size_t iMessage = random() % nMessages;
159 setup_inout_strs(messages[iMessage]);
160 while (anything_to_receive() ||
161 !circular_buffer_is_empty_uint8(out_buf) || iExtraIters < 15) {
162 if (anything_to_receive()) {
163 circular_buffer_push_back_uint8(in_buf, receive_in());
164 }
165 if (!circular_buffer_is_empty_uint8(in_buf)) {
167 &asc, &ascVersion, &appVersion, &command, dataBuffer, &dataLen);
168 if (command != '\0') {
170 &asc, ascVersion, appVersion, command, dataBuffer, dataLen);
171 }
172 }
173 if (!circular_buffer_is_empty_uint8(out_buf)) {
174 send_out(circular_buffer_pop_front_uint8(out_buf));
175 }
176 if (!(anything_to_receive() ||
178 iExtraIters++;
179 }
180 // printf("######################################\n");
181 // printf("iExtraIters: %zu\n",iExtraIters);
182 // circular_buffer_print_uint8(in_buf,stdout);
183 // circular_buffer_print_uint8(out_buf,stdout);
184 }
185 // printf("Expected: '%s'\n",messages[iMessage]);
186 // printf("Observed: '%s'\n",output_str);
187 // circular_buffer_print_uint8(in_buf,stdout);
188 // circular_buffer_print_uint8(out_buf,stdout);
189 TEST_ASSERT_EQUAL_STRING(messages[iMessage], output_str);
190 }
191 }
192 Catch(e1) {
193 printf("Uncaught exception: %u\n", e1);
194 TEST_FAIL_MESSAGE("Uncaught exception!");
195 }
196}
197
198void test_ascii_serial_com_loopback_random_order_bad_messages(void) {
199
200 char ascVersion, appVersion, command, dataBuffer[MAXDATALEN];
201 size_t dataLen;
202
207 size_t iExtraIters = 0;
208
209 const size_t nTries = 200;
210 for (size_t iTry = 0; iTry < nTries; iTry++) {
211 bool isBadMessage = random() % 5000 < 500;
212 if (iTry == nTries - 1)
213 isBadMessage = false;
214 if (isBadMessage) {
215 const size_t iBadMessage = random() % nBadMessages;
216 setup_inout_strs(badMessages[iBadMessage]);
217 thisMessage = badMessages[iBadMessage];
218 } else {
219 const size_t iMessage = random() % nMessages;
220 setup_inout_strs(messages[iMessage]);
221 thisMessage = messages[iMessage];
222 }
223 // printf("iTry: %zu isBad: %d thisMessage:
224 // %s\n",iTry,isBadMessage,thisMessage);
225 while (anything_to_receive() || !circular_buffer_is_empty_uint8(out_buf) ||
226 iExtraIters < 15) {
227 Try {
228 if (anything_to_receive()) {
229 circular_buffer_push_back_uint8(in_buf, receive_in());
230 }
231 if (!circular_buffer_is_empty_uint8(in_buf)) {
233 &asc, &ascVersion, &appVersion, &command, dataBuffer, &dataLen);
234 if (command != '\0') {
236 &asc, ascVersion, appVersion, command, dataBuffer, dataLen);
237 }
238 }
239 if (!circular_buffer_is_empty_uint8(out_buf)) {
240 send_out(circular_buffer_pop_front_uint8(out_buf));
241 }
242 if (!(anything_to_receive() ||
244 iExtraIters++;
245 }
246 // printf("######################################\n");
247 // printf("iExtraIters: %zu\n",iExtraIters);
248 // circular_buffer_print_uint8(in_buf,stdout);
249 // circular_buffer_print_uint8(out_buf,stdout);
250 }
251 Catch(e1) {
252 if (e1 == ASC_ERROR_INVALID_FRAME_PERIOD) {
253 printf("Uncaught exception: ASC_ERROR_INVALID_FRAME_PERIOD\n");
254 // TEST_FAIL_MESSAGE("Uncaught exception
255 // ASC_ERROR_INVALID_FRAME_PERIOD!");
256 } else {
257 printf("Uncaught exception: %u\n", e1);
258 TEST_FAIL_MESSAGE("Uncaught exception!");
259 }
260 }
261 }
262 if (isBadMessage) {
263 TEST_ASSERT_EQUAL_STRING("", output_str);
264 } else {
265 // printf("Expected: '%s'\n",messages[iMessage]);
266 // printf("Observed: '%s'\n",output_str);
267 // circular_buffer_print_uint8(in_buf,stdout);
268 // circular_buffer_print_uint8(out_buf,stdout);
269 TEST_ASSERT_EQUAL_STRING(thisMessage, output_str);
270 }
271 }
272}
273
274int main(void) {
275 UNITY_BEGIN();
276 RUN_TEST(test_ascii_serial_com_loopback);
277 RUN_TEST(test_ascii_serial_com_loopback_random_order);
278 RUN_TEST(test_ascii_serial_com_loopback_random_order_bad_messages);
279 return UNITY_END();
280}
circular_buffer_uint8 * ascii_serial_com_get_output_buffer(ascii_serial_com *asc)
ASCII Serial Com get output buffer.
void ascii_serial_com_init(ascii_serial_com *asc)
ASCII Serial Com Interface init method.
void ascii_serial_com_put_message_in_output_buffer(ascii_serial_com *asc, char ascVersion, char appVersion, char command, const char *data, size_t dataLen)
ASCII Serial Com Pack and put message in output buffer.
void ascii_serial_com_get_message_from_input_buffer(ascii_serial_com *asc, char *ascVersion, char *appVersion, char *command, char *data, size_t *dataLen)
ASCII Serial Com pop message from input buffer and unpack.
circular_buffer_uint8 * ascii_serial_com_get_input_buffer(ascii_serial_com *asc)
ASCII Serial Com get input buffer.
uint8_t circular_buffer_pop_front_uint8(circular_buffer_uint8 *circ_buf)
circular buffer pop front
bool circular_buffer_is_empty_uint8(const circular_buffer_uint8 *circ_buf)
circular buffer get if empty
void circular_buffer_push_back_uint8(circular_buffer_uint8 *circ_buf, const uint8_t element)
circular buffer push back
ASCII Serial Com Interface State struct.
circular buffer struct