Skip to content

Commit 8952760

Browse files
author
Cruz Monrreal
authored
Merge pull request #9033 from fkjagodzinski/fix-stream
Fix Stream for IAR toolchain
2 parents 61f1c1c + 91e9010 commit 8952760

File tree

2 files changed

+175
-19
lines changed

2 files changed

+175
-19
lines changed

TESTS/mbed_platform/Stream/main.cpp

Lines changed: 173 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,196 @@
1818
#include "utest/utest.h"
1919
#include "unity/unity.h"
2020
#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+
*/
2136

2237
using utest::v1::Case;
2338

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+
2444
class Loopback : public Stream {
2545
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+
}
2754

28-
protected:
29-
virtual int _getc()
55+
virtual ~Loopback()
56+
{
57+
}
58+
59+
int test_vprintf(const char *fmt, ...)
3060
{
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;
3267
}
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:
3380
virtual int _putc(int c)
3481
{
35-
_c = c;
82+
if (_p_index >= LOOPBACK_BUFF_SIZE) {
83+
return -1;
84+
}
85+
_buff[_p_index++] = (int8_t)c;
3686
return c;
3787
}
88+
89+
virtual int _getc()
90+
{
91+
if (_g_index >= LOOPBACK_BUFF_SIZE) {
92+
return -1;
93+
}
94+
return _buff[_g_index++];
95+
}
96+
3897
private:
39-
char _c;
98+
int8_t _buff[LOOPBACK_BUFF_SIZE];
99+
size_t _p_index;
100+
size_t _g_index;
40101
};
41102

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+
*/
44110
void test_putc_getc()
45111
{
112+
char char_buff[2] = {'a', 'b'};
113+
Loopback loop("loopback");
46114
int ret;
47-
char char_buf[2] = {'a', 'b'};
48115

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);
51118
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);
55122
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);
58211
}
59212

60213
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)
64217
}
65218

66219
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)
68224
};
69225

70226
utest::v1::Specification specification(test_setup, cases);

platform/Stream.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ int Stream::printf(const char *format, ...)
147147
lock();
148148
std::va_list arg;
149149
va_start(arg, format);
150-
fflush(_file);
150+
std::fseek(_file, 0, SEEK_CUR);
151151
int r = vfprintf(_file, format, arg);
152152
va_end(arg);
153153
unlock();
@@ -169,7 +169,7 @@ int Stream::scanf(const char *format, ...)
169169
int Stream::vprintf(const char *format, std::va_list args)
170170
{
171171
lock();
172-
fflush(_file);
172+
std::fseek(_file, 0, SEEK_CUR);
173173
int r = vfprintf(_file, format, args);
174174
unlock();
175175
return r;

0 commit comments

Comments
 (0)