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 `man 3 fdopen`:
27
+ *
28
+ * Reads and writes may be intermixed on read/write streams in any order. Note
29
+ * that ANSI C requires that a file positioning function intervene between
30
+ * output and input, unless an input operation encounters end-of-file. (If
31
+ * this condition is not met, then a read is allowed to return the result
32
+ * of writes other than the most recent.) Therefore it is good practice (and
33
+ * indeed sometimes necessary under Linux) to put an fseek(3) or fgetpos(3)
34
+ * operation between write and read operations on such a stream. This operation
35
+ * may be an apparent no-op (as in fseek(..., 0L, SEEK_CUR) called for its
36
+ * synchronizing side effect).
37
+ */
21
38
22
39
using utest::v1::Case;
23
40
41
+ const char FMT[] = " Foo%02ibar." ;
42
+ const size_t FORMATTED_STR_SIZE = 3 + 2 + 4 + 1 ;
43
+ // The test Stream instance has to be able to store two printf() output strings.
44
+ const size_t LOOPBACK_BUFF_SIZE = 2 * FORMATTED_STR_SIZE;
45
+
24
46
class Loopback : public Stream {
25
47
public:
26
- Loopback (const char *name = NULL ) : Stream(name) {}
48
+ Loopback (const char *name = NULL ) : Stream(name)
49
+ {
50
+ // The `fgets()` stops reading after a newline or EOF.
51
+ // Fill the buffer with newlines to simplify fgets() usage in this test.
52
+ memset (_buff, ' \n ' , LOOPBACK_BUFF_SIZE);
53
+ _p_index = 0 ;
54
+ _g_index = 0 ;
55
+ }
27
56
28
- protected:
29
- virtual int _getc ()
57
+ virtual ~Loopback ()
58
+ {
59
+ }
60
+
61
+ int test_vprintf (const char *fmt, ...)
30
62
{
31
- return _c;
63
+ int rc = -1 ;
64
+ std::va_list args;
65
+ va_start (args, fmt);
66
+ rc = vprintf (fmt, args);
67
+ va_end (args);
68
+ return rc;
32
69
}
70
+
71
+ int test_vscanf (const char *fmt, ...)
72
+ {
73
+ int rc = EOF;
74
+ std::va_list args;
75
+ va_start (args, fmt);
76
+ rc = vscanf (fmt, args);
77
+ va_end (args);
78
+ return rc;
79
+ }
80
+
81
+ protected:
33
82
virtual int _putc (int c)
34
83
{
35
- _c = c;
84
+ if (_p_index >= LOOPBACK_BUFF_SIZE) {
85
+ return -1 ;
86
+ }
87
+ _buff[_p_index++] = (int8_t )c;
36
88
return c;
37
89
}
90
+
91
+ virtual int _getc ()
92
+ {
93
+ if (_g_index >= LOOPBACK_BUFF_SIZE) {
94
+ return -1 ;
95
+ }
96
+ return _buff[_g_index++];
97
+ }
98
+
38
99
private:
39
- char _c;
100
+ int8_t _buff[LOOPBACK_BUFF_SIZE];
101
+ size_t _p_index;
102
+ size_t _g_index;
40
103
};
41
104
42
- Loopback loop (" loopback" );
43
-
105
+ /* Test intermixed Stream::putc() / Stream::getc().
106
+ *
107
+ * Given a Stream object,
108
+ * when a write/read/write/read sequence is executed
109
+ * with the use of Stream::putc() and Stream::getc() methods,
110
+ * then all operations succeed.
111
+ */
44
112
void test_putc_getc ()
45
113
{
114
+ char char_buff[2 ] = {' a' , ' b' };
115
+ Loopback loop (" loopback" );
46
116
int ret;
47
- char char_buf[2 ] = {' a' , ' b' };
48
117
49
- ret = loop.putc (char_buf [0 ]);
50
- TEST_ASSERT_EQUAL_INT (char_buf [0 ], ret);
118
+ ret = loop.putc (char_buff [0 ]);
119
+ TEST_ASSERT_EQUAL_INT (char_buff [0 ], ret);
51
120
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);
121
+ TEST_ASSERT_EQUAL_INT (char_buff [0 ], ret);
122
+ ret = loop.putc (char_buff [1 ]);
123
+ TEST_ASSERT_EQUAL_INT (char_buff [1 ], ret);
55
124
ret = loop.getc ();
56
- TEST_ASSERT_EQUAL_INT (char_buf[1 ], ret);
57
- return ;
125
+ TEST_ASSERT_EQUAL_INT (char_buff[1 ], ret);
126
+ }
127
+
128
+ /* Test intermixed Stream::puts() / Stream::gets().
129
+ *
130
+ * Given a Stream object,
131
+ * when a write/read/write/read sequence is executed,
132
+ * with the use of Stream::puts() and Stream::gets() methods,
133
+ * then all operations succeed.
134
+ */
135
+ void test_puts_gets ()
136
+ {
137
+ const size_t STR_LEN = 3 ;
138
+ const size_t STR_SIZE = STR_LEN + 1 ; // +1 for '\0'
139
+ char strings[2 ][STR_SIZE] = {" Foo" , " Bar" };
140
+ const size_t GETS_BUFF_SIZE = STR_LEN + 2 ; // +1 for '\n' (gets() stops AFTER a '\n'), +1 for '\0'
141
+ char g_buff[GETS_BUFF_SIZE] = {};
142
+ Loopback loop (" loopback" );
143
+ int p_rc;
144
+ char *g_rc;
145
+
146
+ p_rc = loop.puts (strings[0 ]);
147
+ TEST_ASSERT (p_rc >= 0 );
148
+ g_rc = loop.gets (g_buff, GETS_BUFF_SIZE);
149
+ TEST_ASSERT_EQUAL_PTR (g_buff, g_rc);
150
+
151
+ p_rc = loop.puts (strings[1 ]);
152
+ TEST_ASSERT (p_rc >= 0 );
153
+ g_rc = loop.gets (g_buff, GETS_BUFF_SIZE);
154
+ TEST_ASSERT_EQUAL_PTR (g_buff, g_rc);
155
+ }
156
+
157
+ /* Test intermixed Stream::printf() / Stream::scanf().
158
+ *
159
+ * Given a Stream object,
160
+ * when a write/read/write/read sequence is executed,
161
+ * with the use of Stream::printf() and Stream::scanf() methods,
162
+ * then all operations succeed.
163
+ */
164
+ void test_printf_scanf ()
165
+ {
166
+ Loopback loop (" loopback" );
167
+ int p_val, g_val, rc;
168
+
169
+ p_val = 42 ;
170
+ g_val = p_val + 1 ;
171
+ rc = loop.printf (FMT, p_val);
172
+ TEST_ASSERT (rc > 0 );
173
+ rc = loop.scanf (FMT, &g_val);
174
+ TEST_ASSERT (rc == 1 );
175
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
176
+
177
+ p_val += 5 ;
178
+ g_val = p_val + 1 ;
179
+ rc = loop.printf (FMT, p_val);
180
+ TEST_ASSERT (rc > 0 );
181
+ rc = loop.scanf (FMT, &g_val);
182
+ TEST_ASSERT (rc == 1 );
183
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
184
+ }
185
+
186
+ /* Test intermixed Stream::vprintf() / Stream::vscanf().
187
+ *
188
+ * Given a Stream object,
189
+ * when a write/read/write/read sequence is executed,
190
+ * with the use of Stream::vprintf() and Stream::vscanf() methods,
191
+ * then all operations succeed.
192
+ */
193
+ void test_vprintf_vscanf ()
194
+ {
195
+ Loopback loop (" loopback" );
196
+ int p_val, g_val, rc;
197
+
198
+ p_val = 42 ;
199
+ g_val = p_val + 1 ;
200
+ rc = loop.test_vprintf (FMT, p_val);
201
+ TEST_ASSERT (rc > 0 );
202
+ rc = loop.test_vscanf (FMT, &g_val);
203
+ TEST_ASSERT (rc == 1 );
204
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
205
+
206
+ p_val += 5 ;
207
+ g_val = p_val + 1 ;
208
+ rc = loop.test_vprintf (FMT, p_val);
209
+ TEST_ASSERT (rc > 0 );
210
+ rc = loop.test_vscanf (FMT, &g_val);
211
+ TEST_ASSERT (rc == 1 );
212
+ TEST_ASSERT_EQUAL_INT (p_val, g_val);
58
213
}
59
214
60
215
utest::v1::status_t test_setup (const size_t number_of_cases)
@@ -64,7 +219,10 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
64
219
}
65
220
66
221
Case cases[] = {
67
- Case (" Test putc/getc" , test_putc_getc)
222
+ Case (" Test putc/getc" , test_putc_getc),
223
+ Case (" Test puts/gets" , test_puts_gets),
224
+ Case (" Test printf/scanf" , test_printf_scanf),
225
+ Case (" Test vprintf/vscanf" , test_vprintf_vscanf)
68
226
};
69
227
70
228
utest::v1::Specification specification (test_setup, cases);
0 commit comments