Skip to content

Commit

Permalink
Merge pull request #9033 from fkjagodzinski/fix-stream
Browse files Browse the repository at this point in the history
Fix Stream for IAR toolchain
  • Loading branch information
Cruz Monrreal authored Dec 11, 2018
2 parents 61f1c1c + 91e9010 commit 8952760
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 19 deletions.
190 changes: 173 additions & 17 deletions TESTS/mbed_platform/Stream/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,196 @@
#include "utest/utest.h"
#include "unity/unity.h"
#include "mbed.h"
#include "Stream.h"

/* This test suite verifies that write/read/write/read sequence can be
* successfully executed on the Stream objects.
*
* A qute from C99 standard, paragraph 7.19.5.3, point 6:
*
* When a file is opened with update mode ('+' as the second or third character in the
* above list of mode argument values), both input and output may be performed on the
* associated stream. However, output shall not be directly followed by input without an
* intervening call to the fflush function or to a file positioning function (fseek,
* fsetpos, or rewind), and input shall not be directly followed by output without an
* intervening call to a file positioning function, unless the input operation encounters end-
* of-file.
*/

using utest::v1::Case;

const char FMT[] = "Foo%02ibar.";
const size_t FORMATTED_STR_SIZE = 3 + 2 + 4 + 1;
// The test Stream instance has to be able to store two printf() output strings.
const size_t LOOPBACK_BUFF_SIZE = 2 * FORMATTED_STR_SIZE;

class Loopback : public Stream {
public:
Loopback(const char *name = NULL) : Stream(name) {}
Loopback(const char *name = NULL) : Stream(name)
{
// The `fgets()` stops reading after a newline or EOF.
// Fill the buffer with newlines to simplify fgets() usage in this test.
memset(_buff, '\n', LOOPBACK_BUFF_SIZE);
_p_index = 0;
_g_index = 0;
}

protected:
virtual int _getc()
virtual ~Loopback()
{
}

int test_vprintf(const char *fmt, ...)
{
return _c;
int rc = -1;
std::va_list args;
va_start(args, fmt);
rc = vprintf(fmt, args);
va_end(args);
return rc;
}

int test_vscanf(const char *fmt, ...)
{
int rc = EOF;
std::va_list args;
va_start(args, fmt);
rc = vscanf(fmt, args);
va_end(args);
return rc;
}

protected:
virtual int _putc(int c)
{
_c = c;
if (_p_index >= LOOPBACK_BUFF_SIZE) {
return -1;
}
_buff[_p_index++] = (int8_t)c;
return c;
}

virtual int _getc()
{
if (_g_index >= LOOPBACK_BUFF_SIZE) {
return -1;
}
return _buff[_g_index++];
}

private:
char _c;
int8_t _buff[LOOPBACK_BUFF_SIZE];
size_t _p_index;
size_t _g_index;
};

Loopback loop("loopback");

/* Test intermixed Stream::putc() / Stream::getc().
*
* Given a Stream object,
* when a write/read/write/read sequence is executed
* with the use of Stream::putc() and Stream::getc() methods,
* then all operations succeed.
*/
void test_putc_getc()
{
char char_buff[2] = {'a', 'b'};
Loopback loop("loopback");
int ret;
char char_buf[2] = {'a', 'b'};

ret = loop.putc(char_buf[0]);
TEST_ASSERT_EQUAL_INT(char_buf[0], ret);
ret = loop.putc(char_buff[0]);
TEST_ASSERT_EQUAL_INT(char_buff[0], ret);
ret = loop.getc();
TEST_ASSERT_EQUAL_INT(char_buf[0], ret);
ret = loop.putc(char_buf[1]);
TEST_ASSERT_EQUAL_INT(char_buf[1], ret);
TEST_ASSERT_EQUAL_INT(char_buff[0], ret);
ret = loop.putc(char_buff[1]);
TEST_ASSERT_EQUAL_INT(char_buff[1], ret);
ret = loop.getc();
TEST_ASSERT_EQUAL_INT(char_buf[1], ret);
return;
TEST_ASSERT_EQUAL_INT(char_buff[1], ret);
}

/* Test intermixed Stream::puts() / Stream::gets().
*
* Given a Stream object,
* when a write/read/write/read sequence is executed,
* with the use of Stream::puts() and Stream::gets() methods,
* then all operations succeed.
*/
void test_puts_gets()
{
const size_t STR_LEN = 3;
const size_t STR_SIZE = STR_LEN + 1; // +1 for '\0'
char strings[2][STR_SIZE] = {"Foo", "Bar"};
const size_t GETS_BUFF_SIZE = STR_LEN + 2; // +1 for '\n' (gets() stops AFTER a '\n'), +1 for '\0'
char g_buff[GETS_BUFF_SIZE] = {};
Loopback loop("loopback");
int p_rc;
char *g_rc;

p_rc = loop.puts(strings[0]);
TEST_ASSERT(p_rc >= 0);
g_rc = loop.gets(g_buff, GETS_BUFF_SIZE);
TEST_ASSERT_EQUAL_PTR(g_buff, g_rc);

p_rc = loop.puts(strings[1]);
TEST_ASSERT(p_rc >= 0);
g_rc = loop.gets(g_buff, GETS_BUFF_SIZE);
TEST_ASSERT_EQUAL_PTR(g_buff, g_rc);
}

/* Test intermixed Stream::printf() / Stream::scanf().
*
* Given a Stream object,
* when a write/read/write/read sequence is executed,
* with the use of Stream::printf() and Stream::scanf() methods,
* then all operations succeed.
*/
void test_printf_scanf()
{
Loopback loop("loopback");
int p_val, g_val, rc;

p_val = 42;
g_val = p_val + 1;
rc = loop.printf(FMT, p_val);
TEST_ASSERT(rc > 0);
rc = loop.scanf(FMT, &g_val);
TEST_ASSERT(rc == 1);
TEST_ASSERT_EQUAL_INT(p_val, g_val);

p_val += 5;
g_val = p_val + 1;
rc = loop.printf(FMT, p_val);
TEST_ASSERT(rc > 0);
rc = loop.scanf(FMT, &g_val);
TEST_ASSERT(rc == 1);
TEST_ASSERT_EQUAL_INT(p_val, g_val);
}

/* Test intermixed Stream::vprintf() / Stream::vscanf().
*
* Given a Stream object,
* when a write/read/write/read sequence is executed,
* with the use of Stream::vprintf() and Stream::vscanf() methods,
* then all operations succeed.
*/
void test_vprintf_vscanf()
{
Loopback loop("loopback");
int p_val, g_val, rc;

p_val = 42;
g_val = p_val + 1;
rc = loop.test_vprintf(FMT, p_val);
TEST_ASSERT(rc > 0);
rc = loop.test_vscanf(FMT, &g_val);
TEST_ASSERT(rc == 1);
TEST_ASSERT_EQUAL_INT(p_val, g_val);

p_val += 5;
g_val = p_val + 1;
rc = loop.test_vprintf(FMT, p_val);
TEST_ASSERT(rc > 0);
rc = loop.test_vscanf(FMT, &g_val);
TEST_ASSERT(rc == 1);
TEST_ASSERT_EQUAL_INT(p_val, g_val);
}

utest::v1::status_t test_setup(const size_t number_of_cases)
Expand All @@ -64,7 +217,10 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
}

Case cases[] = {
Case("Test putc/getc", test_putc_getc)
Case("Test putc/getc", test_putc_getc),
Case("Test puts/gets", test_puts_gets),
Case("Test printf/scanf", test_printf_scanf),
Case("Test vprintf/vscanf", test_vprintf_vscanf)
};

utest::v1::Specification specification(test_setup, cases);
Expand Down
4 changes: 2 additions & 2 deletions platform/Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ int Stream::printf(const char *format, ...)
lock();
std::va_list arg;
va_start(arg, format);
fflush(_file);
std::fseek(_file, 0, SEEK_CUR);
int r = vfprintf(_file, format, arg);
va_end(arg);
unlock();
Expand All @@ -169,7 +169,7 @@ int Stream::scanf(const char *format, ...)
int Stream::vprintf(const char *format, std::va_list args)
{
lock();
fflush(_file);
std::fseek(_file, 0, SEEK_CUR);
int r = vfprintf(_file, format, args);
unlock();
return r;
Expand Down

0 comments on commit 8952760

Please sign in to comment.