18
18
#include " utest/utest.h"
19
19
#include " unity/unity.h"
20
20
#include " mbed.h"
21
+ #include " Stream.h"
22
+
23
+ /* This test suite verifies that write/read/write/read sequence can be
24
+ * successfully executed on the Stream objects.
25
+ *
26
+ * A qute from C99 standard, paragraph 7.19.5.3, point 6:
27
+ *
28
+ * When a file is opened with update mode ('+' as the second or third character in the
29
+ * above list of mode argument values), both input and output may be performed on the
30
+ * associated stream. However, output shall not be directly followed by input without an
31
+ * intervening call to the fflush function or to a file positioning function (fseek,
32
+ * fsetpos, or rewind), and input shall not be directly followed by output without an
33
+ * intervening call to a file positioning function, unless the input operation encounters end-
34
+ * of-file.
35
+ */
21
36
22
37
using utest::v1::Case;
23
38
39
+ const char FMT[] = " Foo%02ibar." ;
40
+ const size_t FORMATTED_STR_SIZE = 3 + 2 + 4 + 1 ;
41
+ // The test Stream instance has to be able to store two printf() output strings.
42
+ const size_t LOOPBACK_BUFF_SIZE = 2 * FORMATTED_STR_SIZE;
43
+
24
44
class Loopback : public Stream {
25
45
public:
26
- Loopback (const char *name = NULL ) : Stream(name) {}
46
+ Loopback (const char *name = NULL ) : Stream(name)
47
+ {
48
+ // The `fgets()` stops reading after a newline or EOF.
49
+ // Fill the buffer with newlines to simplify fgets() usage in this test.
50
+ memset (_buff, ' \n ' , LOOPBACK_BUFF_SIZE);
51
+ _p_index = 0 ;
52
+ _g_index = 0 ;
53
+ }
27
54
28
- protected:
29
- virtual int _getc ()
55
+ virtual ~Loopback ()
56
+ {
57
+ }
58
+
59
+ int test_vprintf (const char *fmt, ...)
30
60
{
31
- return _c;
61
+ int rc = -1 ;
62
+ std::va_list args;
63
+ va_start (args, fmt);
64
+ rc = vprintf (fmt, args);
65
+ va_end (args);
66
+ return rc;
32
67
}
68
+
69
+ int test_vscanf (const char *fmt, ...)
70
+ {
71
+ int rc = EOF;
72
+ std::va_list args;
73
+ va_start (args, fmt);
74
+ rc = vscanf (fmt, args);
75
+ va_end (args);
76
+ return rc;
77
+ }
78
+
79
+ protected:
33
80
virtual int _putc (int c)
34
81
{
35
- _c = c;
82
+ if (_p_index >= LOOPBACK_BUFF_SIZE) {
83
+ return -1 ;
84
+ }
85
+ _buff[_p_index++] = (int8_t )c;
36
86
return c;
37
87
}
88
+
89
+ virtual int _getc ()
90
+ {
91
+ if (_g_index >= LOOPBACK_BUFF_SIZE) {
92
+ return -1 ;
93
+ }
94
+ return _buff[_g_index++];
95
+ }
96
+
38
97
private:
39
- char _c;
98
+ int8_t _buff[LOOPBACK_BUFF_SIZE];
99
+ size_t _p_index;
100
+ size_t _g_index;
40
101
};
41
102
42
- Loopback loop (" loopback" );
43
-
103
+ /* Test intermixed Stream::putc() / Stream::getc().
104
+ *
105
+ * Given a Stream object,
106
+ * when a write/read/write/read sequence is executed
107
+ * with the use of Stream::putc() and Stream::getc() methods,
108
+ * then all operations succeed.
109
+ */
44
110
void test_putc_getc ()
45
111
{
112
+ char char_buff[2 ] = {' a' , ' b' };
113
+ Loopback loop (" loopback" );
46
114
int ret;
47
- char char_buf[2 ] = {' a' , ' b' };
48
115
49
- ret = loop.putc (char_buf [0 ]);
50
- TEST_ASSERT_EQUAL_INT (char_buf [0 ], ret);
116
+ ret = loop.putc (char_buff [0 ]);
117
+ TEST_ASSERT_EQUAL_INT (char_buff [0 ], ret);
51
118
ret = loop.getc ();
52
- TEST_ASSERT_EQUAL_INT (char_buf [0 ], ret);
53
- ret = loop.putc (char_buf [1 ]);
54
- TEST_ASSERT_EQUAL_INT (char_buf [1 ], ret);
119
+ TEST_ASSERT_EQUAL_INT (char_buff [0 ], ret);
120
+ ret = loop.putc (char_buff [1 ]);
121
+ TEST_ASSERT_EQUAL_INT (char_buff [1 ], ret);
55
122
ret = loop.getc ();
56
- TEST_ASSERT_EQUAL_INT (char_buf[1 ], ret);
57
- return ;
123
+ TEST_ASSERT_EQUAL_INT (char_buff[1 ], ret);
124
+ }
125
+
126
+ /* Test intermixed Stream::puts() / Stream::gets().
127
+ *
128
+ * Given a Stream object,
129
+ * when a write/read/write/read sequence is executed,
130
+ * with the use of Stream::puts() and Stream::gets() methods,
131
+ * then all operations succeed.
132
+ */
133
+ void test_puts_gets ()
134
+ {
135
+ const size_t STR_LEN = 3 ;
136
+ const size_t STR_SIZE = STR_LEN + 1 ; // +1 for '\0'
137
+ char strings[2 ][STR_SIZE] = {" Foo" , " Bar" };
138
+ const size_t GETS_BUFF_SIZE = STR_LEN + 2 ; // +1 for '\n' (gets() stops AFTER a '\n'), +1 for '\0'
139
+ char g_buff[GETS_BUFF_SIZE] = {};
140
+ Loopback loop (" loopback" );
141
+ int p_rc;
142
+ char *g_rc;
143
+
144
+ p_rc = loop.puts (strings[0 ]);
145
+ TEST_ASSERT (p_rc >= 0 );
146
+ g_rc = loop.gets (g_buff, GETS_BUFF_SIZE);
147
+ TEST_ASSERT_EQUAL_PTR (g_buff, g_rc);
148
+
149
+ p_rc = loop.puts (strings[1 ]);
150
+ TEST_ASSERT (p_rc >= 0 );
151
+ g_rc = loop.gets (g_buff, GETS_BUFF_SIZE);
152
+ TEST_ASSERT_EQUAL_PTR (g_buff, g_rc);
153
+ }
154
+
155
+ /* Test intermixed Stream::printf() / Stream::scanf().
156
+ *
157
+ * Given a Stream object,
158
+ * when a write/read/write/read sequence is executed,
159
+ * with the use of Stream::printf() and Stream::scanf() methods,
160
+ * then all operations succeed.
161
+ */
162
+ void test_printf_scanf ()
163
+ {
164
+ Loopback loop (" loopback" );
165
+ int p_val, g_val, rc;
166
+
167
+ p_val = 42 ;
168
+ g_val = p_val + 1 ;
169
+ rc = loop.printf (FMT, p_val);
170
+ TEST_ASSERT (rc > 0 );
171
+ rc = loop.scanf (FMT, &g_val);
172
+ TEST_ASSERT (rc == 1 );
173
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
174
+
175
+ p_val += 5 ;
176
+ g_val = p_val + 1 ;
177
+ rc = loop.printf (FMT, p_val);
178
+ TEST_ASSERT (rc > 0 );
179
+ rc = loop.scanf (FMT, &g_val);
180
+ TEST_ASSERT (rc == 1 );
181
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
182
+ }
183
+
184
+ /* Test intermixed Stream::vprintf() / Stream::vscanf().
185
+ *
186
+ * Given a Stream object,
187
+ * when a write/read/write/read sequence is executed,
188
+ * with the use of Stream::vprintf() and Stream::vscanf() methods,
189
+ * then all operations succeed.
190
+ */
191
+ void test_vprintf_vscanf ()
192
+ {
193
+ Loopback loop (" loopback" );
194
+ int p_val, g_val, rc;
195
+
196
+ p_val = 42 ;
197
+ g_val = p_val + 1 ;
198
+ rc = loop.test_vprintf (FMT, p_val);
199
+ TEST_ASSERT (rc > 0 );
200
+ rc = loop.test_vscanf (FMT, &g_val);
201
+ TEST_ASSERT (rc == 1 );
202
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
203
+
204
+ p_val += 5 ;
205
+ g_val = p_val + 1 ;
206
+ rc = loop.test_vprintf (FMT, p_val);
207
+ TEST_ASSERT (rc > 0 );
208
+ rc = loop.test_vscanf (FMT, &g_val);
209
+ TEST_ASSERT (rc == 1 );
210
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
58
211
}
59
212
60
213
utest::v1::status_t test_setup (const size_t number_of_cases)
@@ -64,7 +217,10 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
64
217
}
65
218
66
219
Case cases[] = {
67
- Case (" Test putc/getc" , test_putc_getc)
220
+ Case (" Test putc/getc" , test_putc_getc),
221
+ Case (" Test puts/gets" , test_puts_gets),
222
+ Case (" Test printf/scanf" , test_printf_scanf),
223
+ Case (" Test vprintf/vscanf" , test_vprintf_vscanf)
68
224
};
69
225
70
226
utest::v1::Specification specification (test_setup, cases);
0 commit comments