Skip to content

Instantly share code, notes, and snippets.

@maciejbocianski
Created February 2, 2018 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maciejbocianski/56b0ffcf7cc3b91b928801bd7d8f93c9 to your computer and use it in GitHub Desktop.
Save maciejbocianski/56b0ffcf7cc3b91b928801bd7d8f93c9 to your computer and use it in GitHub Desktop.
IAR file test
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TestFile.h"
#include "mbed.h"
/** Test fopen and fclose
*
* Given a file to be opened
*
* When the file is open
* Then returned file descriptor is valid
*
* When the file is closed
* Then underneath retargeting layer function is called
* and the fclose function return with succeed
*
*/
void test_fopen_fclose()
{
std::FILE *file;
const uint32_t FS = 5;
TestFile<FS> fh;
printf("\t>>> test_fopen_fclose\r\n");
file = fdopen((FileHandle*)&fh, "w+");
MBED_ASSERT(file);
TestFile<FS>::resetFunctionCallHistory();
int ret = std::fclose(file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnClose));
MBED_ASSERT(0 == ret);
printf("\t<<< test_fopen_fclose\r\n");
}
/** Test fwrite and fread
*
* Given already opened file
*
* When write some data to file
* Then underneath retargeting layer write function is called
* fwrite return number of successfully written elements
* when not all elements were written stream error is set
*
* When read previously written data from file
* Then underneath retargeting layer read function is called
* fread return number of successfully read elements
* read data match previously written
* when read less then expected stream eof is set
*
*/
void test_fwrite_fread()
{
std::FILE *file;
const uint32_t FS = 5;
TestFile<FS> fh;
char read_buf[16];
const char *str1 = "abc";
const char *str2 = "def";
const uint32_t str1_size = strlen(str1);
const uint32_t str2_size = strlen(str2);
std::size_t write_ret;
std::size_t read_ret;
printf("\t>>> test_fwrite_fread\r\n");
file = fdopen(&fh, "w+");
MBED_ASSERT(file);
std::setbuf(file, NULL);
// write 3; expected written 3
TestFile<FS>::resetFunctionCallHistory();
write_ret = std::fwrite(str1, 1, str1_size, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(str1_size == write_ret);
//#ifndef __ICCARM__ // prevents IAR infinite loop
// write 3; expected written 2
TestFile<FS>::resetFunctionCallHistory();
write_ret = std::fwrite(str2, 1, str2_size, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(std::ferror(file) != 0);
std::clearerr(file); // for ARMCC
#ifndef __ARMCC_VERSION
// ARMCC returns 0 here instead of number of elements successfully written
MBED_ASSERT((str2_size - 1) == write_ret);
#endif
// write 3; expected written 0
TestFile<FS>::resetFunctionCallHistory();
write_ret = std::fwrite(str1, 1, str1_size, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(std::ferror(file) != 0);
MBED_ASSERT(0 == write_ret);
//#endif
//std::fseek(file, 0, SEEK_SET);
std::rewind(file);
// read 3; expected read 3
TestFile<FS>::resetFunctionCallHistory();
read_ret = std::fread(read_buf, 1, str1_size, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(str1_size == read_ret);
MBED_ASSERT(0 == strncmp(str1, read_buf, str1_size));
//#ifndef __ICCARM__
// read 3; expected read 2
TestFile<FS>::resetFunctionCallHistory();
read_ret = std::fread(read_buf, 1, str2_size, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(std::feof(file) != 0);
std::clearerr(file); // for ARMCC
MBED_ASSERT((str2_size - 1) == read_ret);
MBED_ASSERT(0 == strncmp(str2, read_buf, str2_size - 1));
// read 3; expected read 0
TestFile<FS>::resetFunctionCallHistory();
read_ret = std::fread(read_buf, 1, str2_size, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(std::feof(file) != 0);
MBED_ASSERT(0 == read_ret);
//#endif
std::fclose(file);
printf("\t<<< test_fwrite_fread\r\n");
}
/** Test fputc and fgetc
*
* Given already opened file
*
* When write some data to file
* Then underneath retargeting layer write function is called
* fputc return written element
* on failure, returns EOF and stream error is sets
*
* When read previously written data from file
* Then underneath retargeting layer read function is called
* fgetc return read element
* read data match previously written
* on failure, returns EOF and stream error/eof is sets respectively
*
*/
void test_fputc_fgetc()
{
std::FILE *file;
const uint32_t FS = 3;
TestFile<FS> fh;
char char_buf[3] = {'a', 'b', 'c' };
int ret;
printf("\t>>> test_fputc_fgetc\r\n");
file = fdopen(&fh, "w+");
assert(file);
std::setbuf(file, NULL);
// write 1; expected written 1
TestFile<FS>::resetFunctionCallHistory();
ret = std::fputc(char_buf[0], file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(char_buf[0] == ret);
// write 1; expected written 1
TestFile<FS>::resetFunctionCallHistory();
ret = std::fputc(char_buf[1], file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(char_buf[1] == ret);
// write 1; expected written 1
TestFile<FS>::resetFunctionCallHistory();
ret = std::fputc(char_buf[2], file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(char_buf[2] == ret);
//#ifndef __ICCARM__ // prevents IAR infinite loop
// write 1; expected written 0
TestFile<FS>::resetFunctionCallHistory();
ret = std::fputc(char_buf[0], file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(std::ferror(file) != 0);
MBED_ASSERT(EOF == ret);
//#endif
std::rewind(file);
// read 1; expected read 1
TestFile<FS>::resetFunctionCallHistory();
ret = std::fgetc(file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(char_buf[0] == ret);
// read 1; expected read 1
TestFile<FS>::resetFunctionCallHistory();
ret = std::fgetc(file);
#ifndef __ICCARM__
// IAR optimize reads
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
#endif
MBED_ASSERT(char_buf[1] == ret);
// read 1; expected read 1
TestFile<FS>::resetFunctionCallHistory();
ret = std::fgetc(file);
#ifndef __ICCARM__
// IAR optimize reads
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
#endif
MBED_ASSERT(char_buf[2] == ret);
//#ifndef __ICCARM__
// read 1; expected read 0
TestFile<FS>::resetFunctionCallHistory();
ret = std::fgetc(file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(std::feof(file) != 0);
MBED_ASSERT(EOF == ret);
//#endif
std::fclose(file);
printf("\t<<< test_fputc_fgetc\r\n");
}
/** Test fputs and fgets
*
* Given already opened file
*
* When write some data to file
* Then underneath retargeting layer write function is called
* on success, returns a non-negative value
* on failure, returns EOF and set stream error
*
* When read previously written data from file
* Then underneath retargeting layer read function is called
* fgets return valid buffer, and read data match previously written
* when read less then expected stream EOF is set
* on failure, stream error is sets
*
*/
void test_fputs_fgets()
{
std::FILE *file;
const uint32_t FS = 5;
TestFile<FS> fh;
const char *str1 = "abc";
const char *str2 = "def";
const uint32_t str1_size = strlen(str1);
const uint32_t str2_size = strlen(str2);
char read_buf[16];
int fputs_ret;
char *fgets_ret;
printf("\t>>> test_fputs_fgets\r\n");
file = fdopen(&fh, "w+");
MBED_ASSERT(file);
std::setbuf(file, NULL);
// write 3; expected written 3
TestFile<FS>::resetFunctionCallHistory();
fputs_ret = std::fputs(str1, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(fputs_ret >= 0);
//#ifndef __ICCARM__ // prevents IAR infinite loop
// write 3; expected written 2
TestFile<FS>::resetFunctionCallHistory();
fputs_ret = std::fputs(str2, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(std::ferror(file) != 0);
std::clearerr(file); // for ARMCC
MBED_ASSERT(EOF == fputs_ret);
// write 3; expected written 0
TestFile<FS>::resetFunctionCallHistory();
fputs_ret = std::fputs(str1, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(std::ferror(file) != 0);
MBED_ASSERT(EOF == fputs_ret);
//#endif
std::rewind(file);
// read 3; expected read 3
TestFile<FS>::resetFunctionCallHistory();
fgets_ret = std::fgets(read_buf, str1_size + 1, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(read_buf == fgets_ret);
MBED_ASSERT(0 == strncmp(read_buf, str1, str1_size));
//#ifndef __ICCARM__
// read 3; expected read 2
TestFile<FS>::resetFunctionCallHistory();
fgets_ret = std::fgets(read_buf, str2_size + 1, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(std::feof(file) != 0);
std::clearerr(file); // for ARMCC
MBED_ASSERT(read_buf == fgets_ret);
MBED_ASSERT(0 == strncmp(read_buf, str2, str2_size - 2));
// read 3; expected read 0
TestFile<FS>::resetFunctionCallHistory();
fgets_ret = std::fgets(read_buf, str2_size + 1, file);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(std::feof(file) != 0);
MBED_ASSERT(NULL == fgets_ret);
//#endif
std::fclose(file);
printf("\t<<< test_fputs_fgets\r\n");
}
/** Test fprintf and fscanf
*
* Given already opened file
*
* When write some data to file
* Then underneath retargeting layer write function is called
* fprintf return number of written components
* fprintf return negative value if an error occurred and set stream error
*
* When read previously written data from file
* Then underneath retargeting layer read function is called
* fscanf return number of read components, and read data match previously written
* when read less then expected stream EOF is set
* on failure, stream error is sets
*
*/
void test_fprintf_fscanf()
{
std::FILE *file;
const uint32_t FS = 5;
TestFile<FS> fh;
const char *str1 = "abc";
const char *str2 = "def";
const uint32_t str1_size = strlen(str1);
const uint32_t str2_size = strlen(str2);
char read_buf[16];
int fprintf_ret;
int fscanf_ret;
printf("\t>>> test_fprintf_fscanf\r\n");
file = fdopen(&fh, "w+");
MBED_ASSERT(file);
std::setbuf(file, NULL);
// write 3; expected written 3
TestFile<FS>::resetFunctionCallHistory();
fprintf_ret = fprintf(file, "%s", str1);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(str1_size == fprintf_ret);
//#ifndef __ICCARM__ // prevents IAR infinite loop
// write 3; expected written 2
TestFile<FS>::resetFunctionCallHistory();
fprintf_ret = fprintf(file, "%s", str2);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(std::ferror(file) != 0);
std::clearerr(file); // for ARMCC
MBED_ASSERT(fprintf_ret < 0);
// write 3; expected written 0
TestFile<FS>::resetFunctionCallHistory();
fprintf_ret = fprintf(file, "%s", str2);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
MBED_ASSERT(std::ferror(file) != 0);
MBED_ASSERT(fprintf_ret < 0);
//#endif
std::rewind(file);
// read 3; expected read 3
TestFile<FS>::resetFunctionCallHistory();
fscanf_ret = fscanf(file, "%3s", read_buf);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(1 == fscanf_ret);
MBED_ASSERT(0 == strncmp(read_buf, str1, str1_size));
//#ifndef __ICCARM__
// read 3; expected read 2
TestFile<FS>::resetFunctionCallHistory();
fscanf_ret = fscanf(file, "%3s", read_buf);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(std::feof(file) != 0);
std::clearerr(file); // for ARMCC
MBED_ASSERT(1 == fscanf_ret);
MBED_ASSERT(0 == strncmp(read_buf, str2, str2_size - 1));
// read 3; expected read 0
TestFile<FS>::resetFunctionCallHistory();
fscanf_ret = fscanf(file, "%3s", read_buf);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
MBED_ASSERT(std::feof(file) != 0);
MBED_ASSERT(EOF == fscanf_ret);
//#endif
std::fclose(file);
printf("\t<<< test_fprintf_fscanf\r\n");
}
/** Test fseek and ftell
*
* Given already opened file is empty
*
* When set the file position indicator via fseek
* Then underneath retargeting layer seek function is called
* fseek return with succeed and ftell return already set position
*
* Given already opened file is not empty
*
* When set the file position indicator via fseek
* Then underneath retargeting layer seek function is called
* fseek return with succeed and ftell return already set position
*
*/
void test_fseek_ftell()
{
std::FILE *file;
long ftell_ret;
int fssek_ret;
const uint32_t FS = 128;
TestFile<FS> fh;
printf("\t>>> test_fseek_ftell\r\n");
file = fdopen(&fh, "w+");
MBED_ASSERT(file);
std::setbuf(file, NULL);
TestFile<FS>::resetFunctionCallHistory();
ftell_ret = std::ftell(file);
MBED_ASSERT(0 == ftell_ret);
TestFile<FS>::resetFunctionCallHistory();
fssek_ret = std::fseek(file, 0, SEEK_CUR);
MBED_ASSERT(0 == fssek_ret);
TestFile<FS>::resetFunctionCallHistory();
fssek_ret = std::fseek(file, 0, SEEK_SET);
MBED_ASSERT(0 == fssek_ret);
TestFile<FS>::resetFunctionCallHistory();
fssek_ret = std::fseek(file, 0, SEEK_END);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnSeek));
MBED_ASSERT(0 == fssek_ret);
const char *str = "Hello world";
const std::size_t size = std::strlen(str);
std::fwrite(str, 1, size, file);
TestFile<FS>::resetFunctionCallHistory();
ftell_ret = std::ftell(file);
MBED_ASSERT(size == ftell_ret);
TestFile<FS>::resetFunctionCallHistory();
fssek_ret = std::fseek(file, 5, SEEK_SET);
MBED_ASSERT(0 == fssek_ret);
ftell_ret = std::ftell(file);
MBED_ASSERT(5 == ftell_ret);
TestFile<FS>::resetFunctionCallHistory();
fssek_ret = std::fseek(file, -5, SEEK_CUR);
MBED_ASSERT(0 == fssek_ret);
ftell_ret = std::ftell(file);
MBED_ASSERT(0 == ftell_ret);
TestFile<FS>::resetFunctionCallHistory();
fssek_ret = std::fseek(file, 0, SEEK_END);
MBED_ASSERT(TestFile<FS>::functionCalled(TestFile<FS>::fnSeek));
MBED_ASSERT(0 == fssek_ret);
ftell_ret = std::ftell(file);
MBED_ASSERT(size == ftell_ret);
std::fclose(file);
printf("\t<<< test_fseek_ftell\r\n");
}
int main()
{
printf(">>> test start\r\n");
test_fopen_fclose();
test_fwrite_fread();
test_fputc_fgetc();
test_fputs_fgets();
test_fprintf_fscanf();
test_fseek_ftell();
printf("<<< test end\r\n");
}
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_TESTFILEHANDLE_H
#define MBED_TESTFILEHANDLE_H
#include "platform/FileHandle.h"
#define POS_IS_VALID(pos) (pos >= 0 && pos < _end)
#define NEW_POS_IS_VALID(pos) (pos >= 0 && pos < (int32_t)FILE_SIZE)
#define SEEK_POS_IS_VALID(pos) (pos >= 0 && pos <= _end)
#define INVALID_POS (-1)
template<uint32_t FILE_SIZE>
class TestFile : public mbed::FileHandle {
public:
TestFile(): _pos(0), _end(0) {}
~TestFile() {}
enum FunctionName {
fnNone, fnRead, fnWrite, fnSeek, fnClose, fnIsatty
};
virtual ssize_t read(void *buffer, size_t size)
{
ssize_t read;
_fnCalled = fnRead;
for(read = 0; (size_t)read < size; read++)
{
if(POS_IS_VALID(_pos)) {
((uint8_t*)buffer)[read] = _data[_pos++];
} else {
break;
}
} // for
return read;
}
virtual ssize_t write(const void *buffer, size_t size)
{
ssize_t written;
_fnCalled = fnWrite;
for(written = 0; (size_t)written < size; written++)
{
if(NEW_POS_IS_VALID(_pos)) {
_data[_pos++] = ((uint8_t*)buffer)[written];
} else {
if(0 == written) {
return -ENOSPC;
}
break;
}
if(_end < _pos) {
_end++;
}
} // for
return written;
}
virtual off_t seek(off_t offset, int whence)
{
_fnCalled = fnSeek;
int32_t new_pos = INVALID_POS;
switch(whence)
{
case SEEK_SET:
new_pos = offset;
break;
case SEEK_CUR:
new_pos = _pos + offset;
break;
case SEEK_END:
new_pos = _end - offset;
break;
default:
// nothing todo
break;
}
if(SEEK_POS_IS_VALID(new_pos)) {
_pos = new_pos;
} else {
return -EINVAL;
}
return _pos;
}
virtual int close()
{
_fnCalled = fnClose;
return 0;
}
static void resetFunctionCallHistory()
{
_fnCalled = fnNone;
}
static bool functionCalled(FunctionName name)
{
return (name == _fnCalled);
}
static FunctionName getFunctionCalled()
{
return _fnCalled;
}
private:
// stores last function call name
static FunctionName _fnCalled;
// file storage
uint8_t _data[FILE_SIZE];
int32_t _pos, _end;
};
template<uint32_t FILE_SIZE>
typename TestFile<FILE_SIZE>::FunctionName TestFile<FILE_SIZE>::_fnCalled;
#endif // MBED_TESTFILEHANDLE_H
@TTornblom
Copy link

Thanks Maciej,

When running this I get the following output on the console:

                                >>> test start
    >>> test_fopen_fclose
    <<< test_fopen_fclose
    >>> test_fwrite_fread

mbed assertation failed: std::ferror(file) != 0, file: C:\Users\thomasto\Projects\fwrite3\fwrite3\main.cpp, line 98

Is this what you expect and that is wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment