1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-27 18:02:17 +03:00

Migrate from astyle to clang-format (#8464)

This commit is contained in:
Maxim Prokhorov
2022-02-20 19:23:33 +03:00
committed by Max Prokhorov
parent 46190b61f1
commit 19b7a29720
241 changed files with 15925 additions and 16197 deletions

View File

@ -1,32 +0,0 @@
# Code formatting rules for Arduino examples, taken from:
#
# https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf
#
mode=c
lineend=linux
style=allman
# 4 spaces indentation
indent=spaces=4
# also indent macros
#indent-preprocessor
# indent classes, switches (and cases), comments starting at column 1
indent-col1-comments
# put a space around operators
pad-oper
# put a space after if/for/while
pad-header
# if you like one-liners, keep them
keep-one-line-statements
attach-closing-while
unpad-paren
pad-oper
remove-comment-prefix
add-braces

View File

@ -1,44 +0,0 @@
# Code formatting rules for Arduino examples, taken from:
#
# https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf
#
mode=c
lineend=linux
# 2 spaces indentation
indent=spaces=2
# also indent macros
#indent-preprocessor
# indent classes, switches (and cases), comments starting at column 1
indent-classes
indent-switches
indent-cases
indent-col1-comments
# put a space around operators
pad-oper
# put a space after if/for/while
pad-header
# if you like one-liners, keep them
keep-one-line-statements
add-braces
style=java
attach-namespaces
attach-classes
attach-inlines
attach-extern-c
indent-modifiers
indent-namespaces
indent-labels
#indent-preproc-block
#indent-preproc-define
#indent-preproc-cond
unpad-paren
add-braces
remove-comment-prefix

View File

@ -2,12 +2,12 @@
#
# CI job for checking examples style
set -ev
set -e -x
org=$(cd ${0%/*}; pwd)
${org}/../restyle.sh
root=$(git rev-parse --show-toplevel)
${root}/tests/restyle.sh
# Revert changes which astyle might have done to the submodules,
# Revert changes which formatter might have done to the submodules,
# as we don't want to fail the build because of the 3rd party libraries
git --version || true
git submodule foreach --recursive 'git reset --hard'

View File

@ -0,0 +1,149 @@
# Taken from https://github.com/arduino/arduino-language-server/blob/e453c5fbd059bae673bb21d028f5ca8e690744be/handler/handler.go#L1769-L1952
# Which will be used in the IDE 2.0+ when 'format sketch' option is selected
Language: Cpp
# LLVM is the default style setting, used when a configuration option is not set here
BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
AlignEscapedNewlines: DontAlign
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: No
BinPackArguments: true
BinPackParameters: true
# Only used when "BreakBeforeBraces" set to "Custom"
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
#AfterObjCDeclaration:
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
# Java-specific
#BreakAfterJavaFieldAnnotations:
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: false
# v12 has various problems with this set to 0 (no limit)
# possible workaround is to set this to 4294967295 aka some large number
# see https://reviews.llvm.org/D96896
ColumnLimit: 0
# "" matches none
CommentPragmas: ""
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: true
DisableFormat: false
# Docs say "Do not use this in config files". The default (LLVM 11.0.1) is "false".
#ExperimentalAutoDetectBinPacking:
FixNamespaceComments: false
ForEachMacros: []
IncludeBlocks: Preserve
IncludeCategories: []
# "" matches none
IncludeIsMainRegex: ""
IncludeIsMainSourceRegex: ""
IndentCaseBlocks: true
IndentCaseLabels: true
IndentExternBlock: Indent
IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
# Java-specific
#JavaImportGroups:
# JavaScript-specific
#JavaScriptQuotes:
#JavaScriptWrapImports
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ""
MacroBlockEnd: ""
# Set to a large number to effectively disable
MaxEmptyLinesToKeep: 100000
NamespaceIndentation: None
NamespaceMacros: []
# Objective C-specific
#ObjCBinPackProtocolList:
#ObjCBlockIndentWidth:
#ObjCBreakBeforeNestedBlockParam:
#ObjCSpaceAfterProperty:
#ObjCSpaceBeforeProtocolList
PenaltyBreakAssignment: 1
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 1
PenaltyBreakFirstLessLess: 1
PenaltyBreakString: 1
PenaltyBreakTemplateDeclaration: 1
PenaltyExcessCharacter: 1
PenaltyReturnTypeOnItsOwnLine: 1
# Used as a fallback if alignment style can't be detected from code (DerivePointerAlignment: true)
PointerAlignment: Right
RawStringFormats: []
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
StatementMacros: []
TabWidth: 2
TypenameMacros: []
# Default to LF if line endings can't be detected from the content (DeriveLineEnding).
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros: []

View File

@ -0,0 +1,29 @@
BasedOnStyle: WebKit
AlignTrailingComments: true
SortIncludes: false
ColumnLimit: 100
KeepEmptyLinesAtTheStartOfBlocks: false
SpaceAfterTemplateKeyword: false
SpaceBeforeInheritanceColon: false
SpacesBeforeTrailingComments: 2
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveBitFields: Consecutive
AlignConsecutiveDeclarations: Consecutive
AlignAfterOpenBracket: Align
AlignOperands: Align
AlwaysBreakTemplateDeclarations: Yes
BreakConstructorInitializers: AfterColon
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakBeforeConceptDeclarations: true
FixNamespaceComments: true
NamespaceIndentation: Inner
BreakBeforeBraces: Allman
IndentWidth: 4
IndentCaseLabels: false

View File

@ -7,29 +7,30 @@ namespace bs
class ArduinoIOHelper
{
public:
ArduinoIOHelper(Stream& stream) : m_stream(stream)
{
}
ArduinoIOHelper(Stream& stream) : m_stream(stream) { }
size_t printf(const char *format, ...)
size_t printf(const char* format, ...)
{
va_list arg;
va_start(arg, format);
char temp[128];
char* buffer = temp;
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
char temp[128];
char* buffer = temp;
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
va_end(arg);
if (len > sizeof(temp) - 1) {
if (len > sizeof(temp) - 1)
{
buffer = new char[len + 1];
if (!buffer) {
if (!buffer)
{
return 0;
}
va_start(arg, format);
ets_vsnprintf(buffer, len + 1, format, arg);
va_end(arg);
}
len = m_stream.write((const uint8_t*) buffer, len);
if (buffer != temp) {
len = m_stream.write((const uint8_t*)buffer, len);
if (buffer != temp)
{
delete[] buffer;
}
return len;
@ -40,16 +41,20 @@ public:
size_t len = 0;
// Can't use Stream::readBytesUntil here because it can't tell the
// difference between timing out and receiving the terminator.
while (len < dest_size - 1) {
while (len < dest_size - 1)
{
int c = m_stream.read();
if (c < 0) {
if (c < 0)
{
delay(1);
continue;
}
if (c == '\r') {
if (c == '\r')
{
continue;
}
if (c == '\n') {
if (c == '\n')
{
dest[len] = 0;
break;
}
@ -64,10 +69,11 @@ protected:
typedef ArduinoIOHelper IOHelper;
inline void fatal() {
inline void fatal()
{
ESP.restart();
}
} // namespace bs
} // namespace bs
#endif //BS_ARDUINO_H
#endif // BS_ARDUINO_H

View File

@ -18,134 +18,162 @@ namespace protocol
#define SS_FLAG_ESCAPE 0x8
typedef enum {
/* parsing the space between arguments */
SS_SPACE = 0x0,
/* parsing an argument which isn't quoted */
SS_ARG = 0x1,
/* parsing a quoted argument */
SS_QUOTED_ARG = 0x2,
/* parsing an escape sequence within unquoted argument */
SS_ARG_ESCAPED = SS_ARG | SS_FLAG_ESCAPE,
/* parsing an escape sequence within a quoted argument */
SS_QUOTED_ARG_ESCAPED = SS_QUOTED_ARG | SS_FLAG_ESCAPE,
} split_state_t;
typedef enum
{
/* parsing the space between arguments */
SS_SPACE = 0x0,
/* parsing an argument which isn't quoted */
SS_ARG = 0x1,
/* parsing a quoted argument */
SS_QUOTED_ARG = 0x2,
/* parsing an escape sequence within unquoted argument */
SS_ARG_ESCAPED = SS_ARG | SS_FLAG_ESCAPE,
/* parsing an escape sequence within a quoted argument */
SS_QUOTED_ARG_ESCAPED = SS_QUOTED_ARG | SS_FLAG_ESCAPE,
} split_state_t;
/* helper macro, called when done with an argument */
#define END_ARG() do { \
char_out = 0; \
argv[argc++] = next_arg_start; \
state = SS_SPACE; \
} while(0);
#define END_ARG() \
do \
{ \
char_out = 0; \
argv[argc++] = next_arg_start; \
state = SS_SPACE; \
} while (0);
/**
* @brief Split command line into arguments in place
*
* - This function finds whitespace-separated arguments in the given input line.
*
* 'abc def 1 20 .3' -> [ 'abc', 'def', '1', '20', '.3' ]
*
* - Argument which include spaces may be surrounded with quotes. In this case
* spaces are preserved and quotes are stripped.
*
* 'abc "123 456" def' -> [ 'abc', '123 456', 'def' ]
*
* - Escape sequences may be used to produce backslash, double quote, and space:
*
* 'a\ b\\c\"' -> [ 'a b\c"' ]
*
* Pointers to at most argv_size - 1 arguments are returned in argv array.
* The pointer after the last one (i.e. argv[argc]) is set to NULL.
*
* @param line pointer to buffer to parse; it is modified in place
* @param argv array where the pointers to arguments are written
* @param argv_size number of elements in argv_array (max. number of arguments will be argv_size
* - 1)
* @return number of arguments found (argc)
*/
inline size_t split_args(char* line, char** argv, size_t argv_size)
{
const int QUOTE = '"';
const int ESCAPE = '\\';
const int SPACE = ' ';
split_state_t state = SS_SPACE;
size_t argc = 0;
char* next_arg_start = line;
char* out_ptr = line;
for (char* in_ptr = line; argc < argv_size - 1; ++in_ptr)
{
int char_in = (unsigned char)*in_ptr;
if (char_in == 0)
{
break;
}
int char_out = -1;
/**
* @brief Split command line into arguments in place
*
* - This function finds whitespace-separated arguments in the given input line.
*
* 'abc def 1 20 .3' -> [ 'abc', 'def', '1', '20', '.3' ]
*
* - Argument which include spaces may be surrounded with quotes. In this case
* spaces are preserved and quotes are stripped.
*
* 'abc "123 456" def' -> [ 'abc', '123 456', 'def' ]
*
* - Escape sequences may be used to produce backslash, double quote, and space:
*
* 'a\ b\\c\"' -> [ 'a b\c"' ]
*
* Pointers to at most argv_size - 1 arguments are returned in argv array.
* The pointer after the last one (i.e. argv[argc]) is set to NULL.
*
* @param line pointer to buffer to parse; it is modified in place
* @param argv array where the pointers to arguments are written
* @param argv_size number of elements in argv_array (max. number of arguments will be argv_size - 1)
* @return number of arguments found (argc)
*/
inline size_t split_args(char *line, char **argv, size_t argv_size)
{
const int QUOTE = '"';
const int ESCAPE = '\\';
const int SPACE = ' ';
split_state_t state = SS_SPACE;
size_t argc = 0;
char *next_arg_start = line;
char *out_ptr = line;
for (char *in_ptr = line; argc < argv_size - 1; ++in_ptr) {
int char_in = (unsigned char) *in_ptr;
if (char_in == 0) {
break;
switch (state)
{
case SS_SPACE:
if (char_in == SPACE)
{
/* skip space */
}
else if (char_in == QUOTE)
{
next_arg_start = out_ptr;
state = SS_QUOTED_ARG;
}
else if (char_in == ESCAPE)
{
next_arg_start = out_ptr;
state = SS_ARG_ESCAPED;
}
else
{
next_arg_start = out_ptr;
state = SS_ARG;
char_out = char_in;
}
break;
case SS_QUOTED_ARG:
if (char_in == QUOTE)
{
END_ARG();
}
else if (char_in == ESCAPE)
{
state = SS_QUOTED_ARG_ESCAPED;
}
else
{
char_out = char_in;
}
break;
case SS_ARG_ESCAPED:
case SS_QUOTED_ARG_ESCAPED:
if (char_in == ESCAPE || char_in == QUOTE || char_in == SPACE)
{
char_out = char_in;
}
else
{
/* unrecognized escape character, skip */
}
state = (split_state_t)(state & (~SS_FLAG_ESCAPE));
break;
case SS_ARG:
if (char_in == SPACE)
{
END_ARG();
}
else if (char_in == ESCAPE)
{
state = SS_ARG_ESCAPED;
}
else
{
char_out = char_in;
}
break;
}
/* need to output anything? */
if (char_out >= 0)
{
*out_ptr = char_out;
++out_ptr;
}
}
int char_out = -1;
switch (state) {
case SS_SPACE:
if (char_in == SPACE) {
/* skip space */
} else if (char_in == QUOTE) {
next_arg_start = out_ptr;
state = SS_QUOTED_ARG;
} else if (char_in == ESCAPE) {
next_arg_start = out_ptr;
state = SS_ARG_ESCAPED;
} else {
next_arg_start = out_ptr;
state = SS_ARG;
char_out = char_in;
}
break;
case SS_QUOTED_ARG:
if (char_in == QUOTE) {
END_ARG();
} else if (char_in == ESCAPE) {
state = SS_QUOTED_ARG_ESCAPED;
} else {
char_out = char_in;
}
break;
case SS_ARG_ESCAPED:
case SS_QUOTED_ARG_ESCAPED:
if (char_in == ESCAPE || char_in == QUOTE || char_in == SPACE) {
char_out = char_in;
} else {
/* unrecognized escape character, skip */
}
state = (split_state_t) (state & (~SS_FLAG_ESCAPE));
break;
case SS_ARG:
if (char_in == SPACE) {
END_ARG();
} else if (char_in == ESCAPE) {
state = SS_ARG_ESCAPED;
} else {
char_out = char_in;
}
break;
}
/* need to output anything? */
if (char_out >= 0) {
*out_ptr = char_out;
++out_ptr;
/* make sure the final argument is terminated */
*out_ptr = 0;
/* finalize the last argument */
if (state != SS_SPACE && argc < argv_size - 1)
{
argv[argc++] = next_arg_start;
}
/* add a NULL at the end of argv */
argv[argc] = NULL;
return argc;
}
/* make sure the final argument is terminated */
*out_ptr = 0;
/* finalize the last argument */
if (state != SS_SPACE && argc < argv_size - 1) {
argv[argc++] = next_arg_start;
}
/* add a NULL at the end of argv */
argv[argc] = NULL;
return argc;
}
} // namespace protocol
} // namespace bs
} // namespace bs
} // namespace protocol
#endif //BS_ARGS_H
#endif // BS_ARGS_H

View File

@ -11,108 +11,120 @@ namespace bs
{
namespace protocol
{
template<typename IO>
void output_test_start(IO& io, const char* file, size_t line, const char* name, const char* desc)
{
io.printf(BS_LINE_PREFIX "start file=\"%s\" line=%d name=\"%s\" desc=\"%s\"\n", file, line, name, desc);
}
template<typename IO>
void output_check_failure(IO& io, size_t line)
{
io.printf(BS_LINE_PREFIX "check_failure line=%d\n", line);
}
template<typename IO>
void output_test_end(IO& io, bool success, size_t checks, size_t failed_checks, size_t line=0)
{
io.printf(BS_LINE_PREFIX "end line=%d result=%d checks=%d failed_checks=%d\n", line, success, checks, failed_checks);
}
template<typename IO>
void output_menu_begin(IO& io)
{
io.printf(BS_LINE_PREFIX "menu_begin\n");
}
template<typename IO>
void output_menu_item(IO& io, int index, const char* name, const char* desc)
{
io.printf(BS_LINE_PREFIX "item id=%d name=\"%s\" desc=\"%s\"\n", index, name, desc);
}
template<typename IO>
void output_menu_end(IO& io)
{
io.printf(BS_LINE_PREFIX "menu_end\n");
}
template<typename IO>
void output_setenv_result(IO& io, const char* key, const char* value)
{
io.printf(BS_LINE_PREFIX "setenv key=\"%s\" value=\"%s\"\n", key, value);
}
template<typename IO>
void output_getenv_result(IO& io, const char* key, const char* value)
{
(void) key;
io.printf(BS_LINE_PREFIX "getenv value=\"%s\"\n", value);
}
template<typename IO>
void output_pretest_result(IO& io, bool res)
{
io.printf(BS_LINE_PREFIX "pretest result=%d\n", res?1:0);
}
template<typename IO>
bool input_handle(IO& io, char* line_buf, size_t line_buf_size, int& test_num)
{
int cb_read = io.read_line(line_buf, line_buf_size);
if (cb_read == 0 || line_buf[0] == '\n') {
return false;
template<typename IO>
void output_test_start(IO& io, const char* file, size_t line, const char* name,
const char* desc)
{
io.printf(BS_LINE_PREFIX "start file=\"%s\" line=%d name=\"%s\" desc=\"%s\"\n", file, line,
name, desc);
}
char* argv[4];
size_t argc = split_args(line_buf, argv, sizeof(argv)/sizeof(argv[0]));
if (argc == 0) {
return false;
template<typename IO>
void output_check_failure(IO& io, size_t line)
{
io.printf(BS_LINE_PREFIX "check_failure line=%d\n", line);
}
if (strcmp(argv[0], "setenv") == 0) {
if (argc != 3) {
template<typename IO>
void output_test_end(IO& io, bool success, size_t checks, size_t failed_checks, size_t line = 0)
{
io.printf(BS_LINE_PREFIX "end line=%d result=%d checks=%d failed_checks=%d\n", line,
success, checks, failed_checks);
}
template<typename IO>
void output_menu_begin(IO& io)
{
io.printf(BS_LINE_PREFIX "menu_begin\n");
}
template<typename IO>
void output_menu_item(IO& io, int index, const char* name, const char* desc)
{
io.printf(BS_LINE_PREFIX "item id=%d name=\"%s\" desc=\"%s\"\n", index, name, desc);
}
template<typename IO>
void output_menu_end(IO& io)
{
io.printf(BS_LINE_PREFIX "menu_end\n");
}
template<typename IO>
void output_setenv_result(IO& io, const char* key, const char* value)
{
io.printf(BS_LINE_PREFIX "setenv key=\"%s\" value=\"%s\"\n", key, value);
}
template<typename IO>
void output_getenv_result(IO& io, const char* key, const char* value)
{
(void)key;
io.printf(BS_LINE_PREFIX "getenv value=\"%s\"\n", value);
}
template<typename IO>
void output_pretest_result(IO& io, bool res)
{
io.printf(BS_LINE_PREFIX "pretest result=%d\n", res ? 1 : 0);
}
template<typename IO>
bool input_handle(IO& io, char* line_buf, size_t line_buf_size, int& test_num)
{
int cb_read = io.read_line(line_buf, line_buf_size);
if (cb_read == 0 || line_buf[0] == '\n')
{
return false;
}
setenv(argv[1], argv[2], 1);
output_setenv_result(io, argv[1], argv[2]);
test_num = -1;
return false; /* we didn't get the test number yet, so return false */
}
if (strcmp(argv[0], "getenv") == 0) {
if (argc != 2) {
char* argv[4];
size_t argc = split_args(line_buf, argv, sizeof(argv) / sizeof(argv[0]));
if (argc == 0)
{
return false;
}
const char* value = getenv(argv[1]);
output_getenv_result(io, argv[1], (value != NULL) ? value : "");
return false;
}
if (strcmp(argv[0], "pretest") == 0) {
if (argc != 1) {
if (strcmp(argv[0], "setenv") == 0)
{
if (argc != 3)
{
return false;
}
setenv(argv[1], argv[2], 1);
output_setenv_result(io, argv[1], argv[2]);
test_num = -1;
return false; /* we didn't get the test number yet, so return false */
}
if (strcmp(argv[0], "getenv") == 0)
{
if (argc != 2)
{
return false;
}
const char* value = getenv(argv[1]);
output_getenv_result(io, argv[1], (value != NULL) ? value : "");
return false;
}
bool res = ::pretest();
output_pretest_result(io, res);
return false;
if (strcmp(argv[0], "pretest") == 0)
{
if (argc != 1)
{
return false;
}
bool res = ::pretest();
output_pretest_result(io, res);
return false;
}
/* not one of the commands, try to parse as test number */
char* endptr;
test_num = (int)strtol(argv[0], &endptr, 10);
if (endptr != argv[0] + strlen(argv[0]))
{
return false;
}
return true;
}
/* not one of the commands, try to parse as test number */
char* endptr;
test_num = (int) strtol(argv[0], &endptr, 10);
if (endptr != argv[0] + strlen(argv[0])) {
return false;
}
return true;
}
} // ::protocol
} // ::bs
} // namespace protocol
} // namespace bs
#endif //BS_PROTOCOL_H
#endif // BS_PROTOCOL_H

View File

@ -9,11 +9,9 @@ namespace bs
class StdIOHelper
{
public:
StdIOHelper()
{
}
StdIOHelper() { }
size_t printf(const char *format, ...)
size_t printf(const char* format, ...)
{
va_list arg;
va_start(arg, format);
@ -25,11 +23,13 @@ public:
size_t read_line(char* dest, size_t dest_size)
{
char* res = fgets(dest, dest_size, stdin);
if (res == NULL) {
if (res == NULL)
{
return 0;
}
size_t len = strlen(dest);
if (dest[len - 1] == '\n') {
if (dest[len - 1] == '\n')
{
dest[len - 1] = 0;
len--;
}
@ -39,10 +39,11 @@ public:
typedef StdIOHelper IOHelper;
inline void fatal() {
inline void fatal()
{
throw std::runtime_error("fatal error");
}
} // namespace bs
} // namespace bs
#endif //BS_STDIO_H
#endif // BS_STDIO_H

View File

@ -20,15 +20,18 @@
namespace bs
{
typedef void(*test_case_func_t)();
typedef void (*test_case_func_t)();
class TestCase
{
public:
TestCase(TestCase* prev, test_case_func_t func, const char* file, size_t line, const char* name, const char* desc)
: m_func(func), m_file(file), m_line(line), m_name(name), m_desc(desc)
TestCase(TestCase* prev, test_case_func_t func, const char* file, size_t line, const char* name,
const char* desc) :
m_func(func),
m_file(file), m_line(line), m_name(name), m_desc(desc)
{
if (prev) {
if (prev)
{
prev->m_next = this;
}
}
@ -60,36 +63,40 @@ public:
const char* desc() const
{
return (m_desc)?m_desc:"";
return (m_desc) ? m_desc : "";
}
protected:
TestCase* m_next = nullptr;
TestCase* m_next = nullptr;
test_case_func_t m_func;
const char* m_file;
size_t m_line;
const char* m_name;
const char* m_desc;
const char* m_file;
size_t m_line;
const char* m_name;
const char* m_desc;
};
struct Registry {
void add(test_case_func_t func, const char* file, size_t line, const char* name, const char* desc)
struct Registry
{
void add(test_case_func_t func, const char* file, size_t line, const char* name,
const char* desc)
{
TestCase* tc = new TestCase(m_last, func, file, line, name, desc);
if (!m_first) {
if (!m_first)
{
m_first = tc;
}
m_last = tc;
}
TestCase* m_first = nullptr;
TestCase* m_last = nullptr;
TestCase* m_last = nullptr;
};
struct Env {
std::function<void(void)> m_check_pass;
struct Env
{
std::function<void(void)> m_check_pass;
std::function<void(size_t)> m_check_fail;
std::function<void(size_t)> m_fail;
Registry m_registry;
Registry m_registry;
};
extern Env g_env;
@ -98,25 +105,27 @@ template<typename IO>
class Runner
{
typedef Runner<IO> Tself;
public:
Runner(IO& io) : m_io(io)
{
g_env.m_check_pass = std::bind(&Tself::check_pass, this);
g_env.m_check_fail = std::bind(&Tself::check_fail, this, std::placeholders::_1);
g_env.m_fail = std::bind(&Tself::fail, this, std::placeholders::_1);
g_env.m_fail = std::bind(&Tself::fail, this, std::placeholders::_1);
}
~Runner()
{
g_env.m_check_pass = 0;
g_env.m_check_fail = 0;
g_env.m_fail = 0;
g_env.m_fail = 0;
}
void run()
{
do {
} while(do_menu());
do
{
} while (do_menu());
}
void check_pass()
@ -132,7 +141,8 @@ public:
void fail(size_t line)
{
protocol::output_test_end(m_io, false, m_check_pass_count + m_check_fail_count, m_check_fail_count, line);
protocol::output_test_end(m_io, false, m_check_pass_count + m_check_fail_count,
m_check_fail_count, line);
bs::fatal();
}
@ -141,22 +151,28 @@ protected:
{
protocol::output_menu_begin(m_io);
int id = 1;
for (TestCase* tc = g_env.m_registry.m_first; tc; tc = tc->next(), ++id) {
for (TestCase* tc = g_env.m_registry.m_first; tc; tc = tc->next(), ++id)
{
protocol::output_menu_item(m_io, id, tc->name(), tc->desc());
}
protocol::output_menu_end(m_io);
while(true) {
int id;
while (true)
{
int id;
char line_buf[BS_LINE_BUF_SIZE];
if (!protocol::input_handle(m_io, line_buf, sizeof(line_buf), id)) {
if (!protocol::input_handle(m_io, line_buf, sizeof(line_buf), id))
{
continue;
}
if (id < 0) {
if (id < 0)
{
return true;
}
TestCase* tc = g_env.m_registry.m_first;
for (int i = 0; i != id - 1 && tc; ++i, tc = tc->next());
if (!tc) {
for (int i = 0; i != id - 1 && tc; ++i, tc = tc->next())
;
if (!tc)
{
bs::fatal();
}
m_check_pass_count = 0;
@ -164,12 +180,13 @@ protected:
protocol::output_test_start(m_io, tc->file(), tc->line(), tc->name(), tc->desc());
tc->run();
bool success = m_check_fail_count == 0;
protocol::output_test_end(m_io, success, m_check_pass_count + m_check_fail_count, m_check_fail_count);
protocol::output_test_end(m_io, success, m_check_pass_count + m_check_fail_count,
m_check_fail_count);
}
}
protected:
IO& m_io;
IO& m_io;
size_t m_check_pass_count;
size_t m_check_fail_count;
};
@ -177,7 +194,8 @@ protected:
class AutoReg
{
public:
AutoReg(test_case_func_t func, const char* file, size_t line, const char* name, const char* desc = nullptr)
AutoReg(test_case_func_t func, const char* file, size_t line, const char* name,
const char* desc = nullptr)
{
g_env.m_registry.add(func, file, line, name, desc);
}
@ -185,39 +203,59 @@ public:
inline void check(bool condition, size_t line)
{
if (!condition) {
if (!condition)
{
g_env.m_check_fail(line);
} else {
}
else
{
g_env.m_check_pass();
}
}
inline void require(bool condition, size_t line)
{
if (!condition) {
if (!condition)
{
g_env.m_check_fail(line);
g_env.m_fail(line);
} else {
}
else
{
g_env.m_check_pass();
}
}
} // ::bs
} // namespace bs
#define BS_NAME_LINE2( name, line ) name##line
#define BS_NAME_LINE( name, line ) BS_NAME_LINE2( name, line )
#define BS_UNIQUE_NAME( name ) BS_NAME_LINE( name, __LINE__ )
#define BS_NAME_LINE2(name, line) name##line
#define BS_NAME_LINE(name, line) BS_NAME_LINE2(name, line)
#define BS_UNIQUE_NAME(name) BS_NAME_LINE(name, __LINE__)
#define TEST_CASE( ... ) \
static void BS_UNIQUE_NAME( TEST_FUNC__ )(); \
namespace{ bs::AutoReg BS_UNIQUE_NAME( test_autoreg__ )( &BS_UNIQUE_NAME( TEST_FUNC__ ), __FILE__, __LINE__, __VA_ARGS__ ); }\
static void BS_UNIQUE_NAME( TEST_FUNC__ )()
#define TEST_CASE(...) \
static void BS_UNIQUE_NAME(TEST_FUNC__)(); \
namespace \
{ \
bs::AutoReg BS_UNIQUE_NAME(test_autoreg__)(&BS_UNIQUE_NAME(TEST_FUNC__), __FILE__, \
__LINE__, __VA_ARGS__); \
} \
static void BS_UNIQUE_NAME(TEST_FUNC__)()
#define CHECK(condition) bs::check((condition), __LINE__)
#define REQUIRE(condition) bs::require((condition), __LINE__)
#define FAIL() bs::g_env.m_fail(__LINE__)
#define BS_ENV_DECLARE() namespace bs { Env g_env; }
#define BS_RUN(...) do { bs::IOHelper helper = bs::IOHelper(__VA_ARGS__); bs::Runner<bs::IOHelper> runner(helper); runner.run(); } while(0);
#define BS_ENV_DECLARE() \
namespace bs \
{ \
Env g_env; \
}
#define BS_RUN(...) \
do \
{ \
bs::IOHelper helper = bs::IOHelper(__VA_ARGS__); \
bs::Runner<bs::IOHelper> runner(helper); \
runner.run(); \
} while (0);
#endif //BSTEST_H
#endif // BSTEST_H

View File

@ -3,21 +3,23 @@
BS_ENV_DECLARE();
int main()
{
while(true) {
try{
while (true)
{
try
{
BS_RUN();
return 0;
}catch(...) {
}
catch (...)
{
printf("Exception\n\n");
}
}
return 1;
}
TEST_CASE("this test runs successfully", "[bluesmoke]")
{
CHECK(1 + 1 == 2);
@ -38,17 +40,12 @@ TEST_CASE("another test which fails and crashes", "[bluesmoke][fail]")
REQUIRE(false);
}
TEST_CASE("third test which should be skipped", "[.]")
{
FAIL();
}
TEST_CASE("this test also runs successfully", "[bluesmoke]")
{
}
TEST_CASE("this test also runs successfully", "[bluesmoke]") { }
TEST_CASE("environment variables can be set and read from python", "[bluesmoke]")
{
@ -57,4 +54,3 @@ TEST_CASE("environment variables can be set and read from python", "[bluesmoke]"
CHECK(strcmp(res, "42") == 0);
setenv("VAR_FROM_TEST", "24", 1);
}

View File

@ -3,8 +3,6 @@
#include <stdlib.h>
#include <errno.h>
#define memcmp memcmp_P
#define memcpy memcpy_P
#define memmem memmem_P
@ -18,416 +16,404 @@
#define strcmp strcmp_P
#define strncmp strncmp_P
_CONST char *it = "<UNSET>"; /* Routine name for message routines. */
static int errors = 0;
_CONST char* it = "<UNSET>"; /* Routine name for message routines. */
static int errors = 0;
/* Complain if condition is not true. */
#define check(thing) checkit(thing, __LINE__)
static void
_DEFUN(checkit,(ok,l),
int ok _AND
int l )
static void _DEFUN(checkit, (ok, l), int ok _AND int l)
{
// newfunc(it);
// line(l);
if (!ok)
{
printf("string.c:%d %s\n", l, it);
++errors;
}
}
// newfunc(it);
// line(l);
/* Complain if first two args don't strcmp as equal. */
#define equal(a, b) funcqual(a,b,__LINE__);
static void
_DEFUN(funcqual,(a,b,l),
char *a _AND
char *b _AND
int l)
{
// newfunc(it);
// line(l);
if (a == NULL && b == NULL) return;
if (strcmp(a,b)) {
printf("string.c:%d (%s)\n", l, it);
if (!ok)
{
printf("string.c:%d %s\n", l, it);
++errors;
}
}
/* Complain if first two args don't strcmp as equal. */
#define equal(a, b) funcqual(a, b, __LINE__);
static void _DEFUN(funcqual, (a, b, l), char* a _AND char* b _AND int l)
{
// newfunc(it);
// line(l);
if (a == NULL && b == NULL)
return;
if (strcmp(a, b))
{
printf("string.c:%d (%s)\n", l, it);
}
}
static char one[50];
static char two[50];
void libm_test_string()
{
/* Test strcmp first because we use it to test other things. */
it = "strcmp";
check(strcmp("", "") == 0); /* Trivial case. */
check(strcmp("a", "a") == 0); /* Identity. */
check(strcmp("abc", "abc") == 0); /* Multicharacter. */
check(strcmp("abc", "abcd") < 0); /* Length mismatches. */
check(strcmp("abcd", "abc") > 0);
check(strcmp("abcd", "abce") < 0); /* Honest miscompares. */
check(strcmp("abce", "abcd") > 0);
check(strcmp("a\103", "a") > 0); /* Tricky if char signed. */
check(strcmp("a\103", "a\003") > 0);
/* Test strcmp first because we use it to test other things. */
it = "strcmp";
check(strcmp("", "") == 0); /* Trivial case. */
check(strcmp("a", "a") == 0); /* Identity. */
check(strcmp("abc", "abc") == 0); /* Multicharacter. */
check(strcmp("abc", "abcd") < 0); /* Length mismatches. */
check(strcmp("abcd", "abc") > 0);
check(strcmp("abcd", "abce") < 0); /* Honest miscompares. */
check(strcmp("abce", "abcd") > 0);
check(strcmp("a\103", "a") > 0); /* Tricky if char signed. */
check(strcmp("a\103", "a\003") > 0);
/* Test strcpy next because we need it to set up other tests. */
it = "strcpy";
check(strcpy(one, "abcd") == one); /* Returned value. */
equal(one, "abcd"); /* Basic test. */
/* Test strcpy next because we need it to set up other tests. */
it = "strcpy";
check(strcpy(one, "abcd") == one); /* Returned value. */
equal(one, "abcd"); /* Basic test. */
(void) strcpy(one, "x");
equal(one, "x"); /* Writeover. */
equal(one+2, "cd"); /* Wrote too much? */
(void)strcpy(one, "x");
equal(one, "x"); /* Writeover. */
equal(one + 2, "cd"); /* Wrote too much? */
(void) strcpy(two, "hi there");
(void) strcpy(one, two);
equal(one, "hi there"); /* Basic test encore. */
equal(two, "hi there"); /* Stomped on source? */
(void)strcpy(two, "hi there");
(void)strcpy(one, two);
equal(one, "hi there"); /* Basic test encore. */
equal(two, "hi there"); /* Stomped on source? */
(void) strcpy(one, "");
equal(one, ""); /* Boundary condition. */
(void)strcpy(one, "");
equal(one, ""); /* Boundary condition. */
/* strcat. */
it = "strcat";
(void) strcpy(one, "ijk");
check(strcat(one, "lmn") == one); /* Returned value. */
equal(one, "ijklmn"); /* Basic test. */
/* strcat. */
it = "strcat";
(void)strcpy(one, "ijk");
check(strcat(one, "lmn") == one); /* Returned value. */
equal(one, "ijklmn"); /* Basic test. */
(void) strcpy(one, "x");
(void) strcat(one, "yz");
equal(one, "xyz"); /* Writeover. */
equal(one+4, "mn"); /* Wrote too much? */
(void)strcpy(one, "x");
(void)strcat(one, "yz");
equal(one, "xyz"); /* Writeover. */
equal(one + 4, "mn"); /* Wrote too much? */
(void) strcpy(one, "gh");
(void) strcpy(two, "ef");
(void) strcat(one, two);
equal(one, "ghef"); /* Basic test encore. */
equal(two, "ef"); /* Stomped on source? */
(void)strcpy(one, "gh");
(void)strcpy(two, "ef");
(void)strcat(one, two);
equal(one, "ghef"); /* Basic test encore. */
equal(two, "ef"); /* Stomped on source? */
(void) strcpy(one, "");
(void) strcat(one, "");
equal(one, ""); /* Boundary conditions. */
(void) strcpy(one, "ab");
(void) strcat(one, "");
equal(one, "ab");
(void) strcpy(one, "");
(void) strcat(one, "cd");
equal(one, "cd");
(void)strcpy(one, "");
(void)strcat(one, "");
equal(one, ""); /* Boundary conditions. */
(void)strcpy(one, "ab");
(void)strcat(one, "");
equal(one, "ab");
(void)strcpy(one, "");
(void)strcat(one, "cd");
equal(one, "cd");
/* strncat - first test it as strcat, with big counts,
then test the count mechanism. */
it = "strncat";
(void) strcpy(one, "ijk");
check(strncat(one, "lmn", 99) == one); /* Returned value. */
equal(one, "ijklmn"); /* Basic test. */
/* strncat - first test it as strcat, with big counts,
then test the count mechanism. */
it = "strncat";
(void)strcpy(one, "ijk");
check(strncat(one, "lmn", 99) == one); /* Returned value. */
equal(one, "ijklmn"); /* Basic test. */
(void) strcpy(one, "x");
(void) strncat(one, "yz", 99);
equal(one, "xyz"); /* Writeover. */
equal(one+4, "mn"); /* Wrote too much? */
(void)strcpy(one, "x");
(void)strncat(one, "yz", 99);
equal(one, "xyz"); /* Writeover. */
equal(one + 4, "mn"); /* Wrote too much? */
(void) strcpy(one, "gh");
(void) strcpy(two, "ef");
(void) strncat(one, two, 99);
equal(one, "ghef"); /* Basic test encore. */
equal(two, "ef"); /* Stomped on source? */
(void)strcpy(one, "gh");
(void)strcpy(two, "ef");
(void)strncat(one, two, 99);
equal(one, "ghef"); /* Basic test encore. */
equal(two, "ef"); /* Stomped on source? */
(void) strcpy(one, "");
(void) strncat(one, "", 99);
equal(one, ""); /* Boundary conditions. */
(void) strcpy(one, "ab");
(void) strncat(one, "", 99);
equal(one, "ab");
(void) strcpy(one, "");
(void) strncat(one, "cd", 99);
equal(one, "cd");
(void)strcpy(one, "");
(void)strncat(one, "", 99);
equal(one, ""); /* Boundary conditions. */
(void)strcpy(one, "ab");
(void)strncat(one, "", 99);
equal(one, "ab");
(void)strcpy(one, "");
(void)strncat(one, "cd", 99);
equal(one, "cd");
(void) strcpy(one, "ab");
(void) strncat(one, "cdef", 2);
equal(one, "abcd"); /* Count-limited. */
(void)strcpy(one, "ab");
(void)strncat(one, "cdef", 2);
equal(one, "abcd"); /* Count-limited. */
(void) strncat(one, "gh", 0);
equal(one, "abcd"); /* Zero count. */
(void)strncat(one, "gh", 0);
equal(one, "abcd"); /* Zero count. */
(void) strncat(one, "gh", 2);
equal(one, "abcdgh"); /* Count _AND length equal. */
it = "strncmp";
/* strncmp - first test as strcmp with big counts";*/
check(strncmp("", "", 99) == 0); /* Trivial case. */
check(strncmp("a", "a", 99) == 0); /* Identity. */
check(strncmp("abc", "abc", 99) == 0); /* Multicharacter. */
check(strncmp("abc", "abcd", 99) < 0); /* Length unequal. */
check(strncmp("abcd", "abc",99) > 0);
check(strncmp("abcd", "abce", 99) < 0); /* Honestly unequal. */
check(strncmp("abce", "abcd",99)>0);
check(strncmp("abce", "abcd", 3) == 0); /* Count limited. */
check(strncmp("abce", "abc", 3) == 0); /* Count == length. */
check(strncmp("abcd", "abce", 4) < 0); /* Nudging limit. */
check(strncmp("abc", "def", 0) == 0); /* Zero count. */
(void)strncat(one, "gh", 2);
equal(one, "abcdgh"); /* Count _AND length equal. */
it = "strncmp";
/* strncmp - first test as strcmp with big counts";*/
check(strncmp("", "", 99) == 0); /* Trivial case. */
check(strncmp("a", "a", 99) == 0); /* Identity. */
check(strncmp("abc", "abc", 99) == 0); /* Multicharacter. */
check(strncmp("abc", "abcd", 99) < 0); /* Length unequal. */
check(strncmp("abcd", "abc", 99) > 0);
check(strncmp("abcd", "abce", 99) < 0); /* Honestly unequal. */
check(strncmp("abce", "abcd", 99) > 0);
check(strncmp("abce", "abcd", 3) == 0); /* Count limited. */
check(strncmp("abce", "abc", 3) == 0); /* Count == length. */
check(strncmp("abcd", "abce", 4) < 0); /* Nudging limit. */
check(strncmp("abc", "def", 0) == 0); /* Zero count. */
/* strncpy - testing is a bit different because of odd semantics. */
it = "strncpy";
check(strncpy(one, "abc", 4) == one); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
/* strncpy - testing is a bit different because of odd semantics. */
it = "strncpy";
check(strncpy(one, "abc", 4) == one); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 2);
equal(one, "xycdefgh"); /* Copy cut by count. */
(void)strcpy(one, "abcdefgh");
(void)strncpy(one, "xyz", 2);
equal(one, "xycdefgh"); /* Copy cut by count. */
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 3); /* Copy cut just before NUL. */
equal(one, "xyzdefgh");
(void)strcpy(one, "abcdefgh");
(void)strncpy(one, "xyz", 3); /* Copy cut just before NUL. */
equal(one, "xyzdefgh");
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 4); /* Copy just includes NUL. */
equal(one, "xyz");
equal(one+4, "efgh"); /* Wrote too much? */
(void)strcpy(one, "abcdefgh");
(void)strncpy(one, "xyz", 4); /* Copy just includes NUL. */
equal(one, "xyz");
equal(one + 4, "efgh"); /* Wrote too much? */
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 5); /* Copy includes padding. */
equal(one, "xyz");
equal(one+4, "");
equal(one+5, "fgh");
(void)strcpy(one, "abcdefgh");
(void)strncpy(one, "xyz", 5); /* Copy includes padding. */
equal(one, "xyz");
equal(one + 4, "");
equal(one + 5, "fgh");
(void) strcpy(one, "abc");
(void) strncpy(one, "xyz", 0); /* Zero-length copy. */
equal(one, "abc");
(void)strcpy(one, "abc");
(void)strncpy(one, "xyz", 0); /* Zero-length copy. */
equal(one, "abc");
(void) strncpy(one, "", 2); /* Zero-length source. */
equal(one, "");
equal(one+1, "");
equal(one+2, "c");
(void)strncpy(one, "", 2); /* Zero-length source. */
equal(one, "");
equal(one + 1, "");
equal(one + 2, "c");
(void) strcpy(one, "hi there");
(void) strncpy(two, one, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
(void)strcpy(one, "hi there");
(void)strncpy(two, one, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
/* strlen. */
it = "strlen";
check(strlen("") == 0); /* Empty. */
check(strlen("a") == 1); /* Single char. */
check(strlen("abcd") == 4); /* Multiple chars. */
/* strlen. */
it = "strlen";
check(strlen("") == 0); /* Empty. */
check(strlen("a") == 1); /* Single char. */
check(strlen("abcd") == 4); /* Multiple chars. */
/* strchr. */
it = "strchr";
check(strchr("abcd", 'z') == NULL); /* Not found. */
(void) strcpy(one, "abcd");
check(strchr(one, 'c') == one+2); /* Basic test. */
check(strchr(one, 'd') == one+3); /* End of string. */
check(strchr(one, 'a') == one); /* Beginning. */
check(strchr(one, '\0') == one+4); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(strchr(one, 'b') == one+1); /* Finding first. */
(void) strcpy(one, "");
check(strchr(one, 'b') == NULL); /* Empty string. */
check(strchr(one, '\0') == one); /* NUL in empty string. */
/* strchr. */
it = "strchr";
check(strchr("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(strchr(one, 'c') == one + 2); /* Basic test. */
check(strchr(one, 'd') == one + 3); /* End of string. */
check(strchr(one, 'a') == one); /* Beginning. */
check(strchr(one, '\0') == one + 4); /* Finding NUL. */
(void)strcpy(one, "ababa");
check(strchr(one, 'b') == one + 1); /* Finding first. */
(void)strcpy(one, "");
check(strchr(one, 'b') == NULL); /* Empty string. */
check(strchr(one, '\0') == one); /* NUL in empty string. */
/* index - just like strchr. */
it = "index";
check(index("abcd", 'z') == NULL); /* Not found. */
(void) strcpy(one, "abcd");
check(index(one, 'c') == one+2); /* Basic test. */
check(index(one, 'd') == one+3); /* End of string. */
check(index(one, 'a') == one); /* Beginning. */
check(index(one, '\0') == one+4); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(index(one, 'b') == one+1); /* Finding first. */
(void) strcpy(one, "");
check(index(one, 'b') == NULL); /* Empty string. */
check(index(one, '\0') == one); /* NUL in empty string. */
/* index - just like strchr. */
it = "index";
check(index("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(index(one, 'c') == one + 2); /* Basic test. */
check(index(one, 'd') == one + 3); /* End of string. */
check(index(one, 'a') == one); /* Beginning. */
check(index(one, '\0') == one + 4); /* Finding NUL. */
(void)strcpy(one, "ababa");
check(index(one, 'b') == one + 1); /* Finding first. */
(void)strcpy(one, "");
check(index(one, 'b') == NULL); /* Empty string. */
check(index(one, '\0') == one); /* NUL in empty string. */
/* strrchr. */
it = "strrchr";
check(strrchr("abcd", 'z') == NULL); /* Not found. */
(void) strcpy(one, "abcd");
check(strrchr(one, 'c') == one+2); /* Basic test. */
check(strrchr(one, 'd') == one+3); /* End of string. */
check(strrchr(one, 'a') == one); /* Beginning. */
check(strrchr(one, '\0') == one+4); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(strrchr(one, 'b') == one+3); /* Finding last. */
(void) strcpy(one, "");
check(strrchr(one, 'b') == NULL); /* Empty string. */
check(strrchr(one, '\0') == one); /* NUL in empty string. */
/* strrchr. */
it = "strrchr";
check(strrchr("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(strrchr(one, 'c') == one + 2); /* Basic test. */
check(strrchr(one, 'd') == one + 3); /* End of string. */
check(strrchr(one, 'a') == one); /* Beginning. */
check(strrchr(one, '\0') == one + 4); /* Finding NUL. */
(void)strcpy(one, "ababa");
check(strrchr(one, 'b') == one + 3); /* Finding last. */
(void)strcpy(one, "");
check(strrchr(one, 'b') == NULL); /* Empty string. */
check(strrchr(one, '\0') == one); /* NUL in empty string. */
/* rindex - just like strrchr. */
it = "rindex";
check(rindex("abcd", 'z') == NULL); /* Not found. */
(void) strcpy(one, "abcd");
check(rindex(one, 'c') == one+2); /* Basic test. */
check(rindex(one, 'd') == one+3); /* End of string. */
check(rindex(one, 'a') == one); /* Beginning. */
check(rindex(one, '\0') == one+4); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(rindex(one, 'b') == one+3); /* Finding last. */
(void) strcpy(one, "");
check(rindex(one, 'b') == NULL); /* Empty string. */
check(rindex(one, '\0') == one); /* NUL in empty string. */
/* rindex - just like strrchr. */
it = "rindex";
check(rindex("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(rindex(one, 'c') == one + 2); /* Basic test. */
check(rindex(one, 'd') == one + 3); /* End of string. */
check(rindex(one, 'a') == one); /* Beginning. */
check(rindex(one, '\0') == one + 4); /* Finding NUL. */
(void)strcpy(one, "ababa");
check(rindex(one, 'b') == one + 3); /* Finding last. */
(void)strcpy(one, "");
check(rindex(one, 'b') == NULL); /* Empty string. */
check(rindex(one, '\0') == one); /* NUL in empty string. */
/* strpbrk - somewhat like strchr. */
it = "strpbrk";
check(strpbrk("abcd", "z") == NULL); /* Not found. */
(void) strcpy(one, "abcd");
check(strpbrk(one, "c") == one+2); /* Basic test. */
check(strpbrk(one, "d") == one+3); /* End of string. */
check(strpbrk(one, "a") == one); /* Beginning. */
check(strpbrk(one, "") == NULL); /* Empty search list. */
check(strpbrk(one, "cb") == one+1); /* Multiple search. */
(void) strcpy(one, "abcabdea");
check(strpbrk(one, "b") == one+1); /* Finding first. */
check(strpbrk(one, "cb") == one+1); /* With multiple search. */
check(strpbrk(one, "db") == one+1); /* Another variant. */
(void) strcpy(one, "");
check(strpbrk(one, "bc") == NULL); /* Empty string. */
check(strpbrk(one, "") == NULL); /* Both strings empty. */
/* strpbrk - somewhat like strchr. */
it = "strpbrk";
check(strpbrk("abcd", "z") == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(strpbrk(one, "c") == one + 2); /* Basic test. */
check(strpbrk(one, "d") == one + 3); /* End of string. */
check(strpbrk(one, "a") == one); /* Beginning. */
check(strpbrk(one, "") == NULL); /* Empty search list. */
check(strpbrk(one, "cb") == one + 1); /* Multiple search. */
(void)strcpy(one, "abcabdea");
check(strpbrk(one, "b") == one + 1); /* Finding first. */
check(strpbrk(one, "cb") == one + 1); /* With multiple search. */
check(strpbrk(one, "db") == one + 1); /* Another variant. */
(void)strcpy(one, "");
check(strpbrk(one, "bc") == NULL); /* Empty string. */
check(strpbrk(one, "") == NULL); /* Both strings empty. */
/* strstr - somewhat like strchr. */
it = "strstr";
check(strstr("z", "abcd") == NULL); /* Not found. */
check(strstr("abx", "abcd") == NULL); /* Dead end. */
(void) strcpy(one, "abcd");
check(strstr(one,"c") == one+2); /* Basic test. */
check(strstr(one, "bc") == one+1); /* Multichar. */
check(strstr(one,"d") == one+3); /* End of string. */
check(strstr(one,"cd") == one+2); /* Tail of string. */
check(strstr(one,"abc") == one); /* Beginning. */
check(strstr(one,"abcd") == one); /* Exact match. */
check(strstr(one,"de") == NULL); /* Past end. */
check(strstr(one,"") == one); /* Finding empty. */
(void) strcpy(one, "ababa");
check(strstr(one,"ba") == one+1); /* Finding first. */
(void) strcpy(one, "");
check(strstr(one, "b") == NULL); /* Empty string. */
check(strstr(one,"") == one); /* Empty in empty string. */
(void) strcpy(one, "bcbca");
check(strstr(one,"bca") == one+2); /* False start. */
(void) strcpy(one, "bbbcabbca");
check(strstr(one,"bbca") == one+1); /* With overlap. */
/* strstr - somewhat like strchr. */
it = "strstr";
check(strstr("z", "abcd") == NULL); /* Not found. */
check(strstr("abx", "abcd") == NULL); /* Dead end. */
(void)strcpy(one, "abcd");
check(strstr(one, "c") == one + 2); /* Basic test. */
check(strstr(one, "bc") == one + 1); /* Multichar. */
check(strstr(one, "d") == one + 3); /* End of string. */
check(strstr(one, "cd") == one + 2); /* Tail of string. */
check(strstr(one, "abc") == one); /* Beginning. */
check(strstr(one, "abcd") == one); /* Exact match. */
check(strstr(one, "de") == NULL); /* Past end. */
check(strstr(one, "") == one); /* Finding empty. */
(void)strcpy(one, "ababa");
check(strstr(one, "ba") == one + 1); /* Finding first. */
(void)strcpy(one, "");
check(strstr(one, "b") == NULL); /* Empty string. */
check(strstr(one, "") == one); /* Empty in empty string. */
(void)strcpy(one, "bcbca");
check(strstr(one, "bca") == one + 2); /* False start. */
(void)strcpy(one, "bbbcabbca");
check(strstr(one, "bbca") == one + 1); /* With overlap. */
/* strspn. */
it = "strspn";
check(strspn("abcba", "abc") == 5); /* Whole string. */
check(strspn("abcba", "ab") == 2); /* Partial. */
check(strspn("abc", "qx") == 0); /* None. */
check(strspn("", "ab") == 0); /* Null string. */
check(strspn("abc", "") == 0); /* Null search list. */
/* strspn. */
it = "strspn";
check(strspn("abcba", "abc") == 5); /* Whole string. */
check(strspn("abcba", "ab") == 2); /* Partial. */
check(strspn("abc", "qx") == 0); /* None. */
check(strspn("", "ab") == 0); /* Null string. */
check(strspn("abc", "") == 0); /* Null search list. */
/* strcspn. */
it = "strcspn";
check(strcspn("abcba", "qx") == 5); /* Whole string. */
check(strcspn("abcba", "cx") == 2); /* Partial. */
check(strcspn("abc", "abc") == 0); /* None. */
check(strcspn("", "ab") == 0); /* Null string. */
check(strcspn("abc", "") == 3); /* Null search list. */
/* strcspn. */
it = "strcspn";
check(strcspn("abcba", "qx") == 5); /* Whole string. */
check(strcspn("abcba", "cx") == 2); /* Partial. */
check(strcspn("abc", "abc") == 0); /* None. */
check(strcspn("", "ab") == 0); /* Null string. */
check(strcspn("abc", "") == 3); /* Null search list. */
/* strtok - the hard one. */
it = "strtok";
(void) strcpy(one, "first, second, third");
equal(strtok(one, ", "), "first"); /* Basic test. */
equal(one, "first");
equal(strtok((char *)NULL, ", "), "second");
equal(strtok((char *)NULL, ", "), "third");
check(strtok((char *)NULL, ", ") == NULL);
(void) strcpy(one, ", first, ");
equal(strtok(one, ", "), "first"); /* Extra delims, 1 tok. */
check(strtok((char *)NULL, ", ") == NULL);
(void) strcpy(one, "1a, 1b; 2a, 2b");
equal(strtok(one, ", "), "1a"); /* Changing delim lists. */
equal(strtok((char *)NULL, "; "), "1b");
equal(strtok((char *)NULL, ", "), "2a");
(void) strcpy(two, "x-y");
equal(strtok(two, "-"), "x"); /* New string before done. */
equal(strtok((char *)NULL, "-"), "y");
check(strtok((char *)NULL, "-") == NULL);
(void) strcpy(one, "a,b, c,, ,d");
equal(strtok(one, ", "), "a"); /* Different separators. */
equal(strtok((char *)NULL, ", "), "b");
equal(strtok((char *)NULL, " ,"), "c"); /* Permute list too. */
equal(strtok((char *)NULL, " ,"), "d");
check(strtok((char *)NULL, ", ") == NULL);
check(strtok((char *)NULL, ", ") == NULL); /* Persistence. */
(void) strcpy(one, ", ");
check(strtok(one, ", ") == NULL); /* No tokens. */
(void) strcpy(one, "");
check(strtok(one, ", ") == NULL); /* Empty string. */
(void) strcpy(one, "abc");
equal(strtok(one, ", "), "abc"); /* No delimiters. */
check(strtok((char *)NULL, ", ") == NULL);
(void) strcpy(one, "abc");
equal(strtok(one, ""), "abc"); /* Empty delimiter list. */
check(strtok((char *)NULL, "") == NULL);
(void) strcpy(one, "abcdefgh");
(void) strcpy(one, "a,b,c");
equal(strtok(one, ","), "a"); /* Basics again... */
equal(strtok((char *)NULL, ","), "b");
equal(strtok((char *)NULL, ","), "c");
check(strtok((char *)NULL, ",") == NULL);
equal(one+6, "gh"); /* Stomped past end? */
equal(one, "a"); /* Stomped old tokens? */
equal(one+2, "b");
equal(one+4, "c");
/* strtok - the hard one. */
it = "strtok";
(void)strcpy(one, "first, second, third");
equal(strtok(one, ", "), "first"); /* Basic test. */
equal(one, "first");
equal(strtok((char*)NULL, ", "), "second");
equal(strtok((char*)NULL, ", "), "third");
check(strtok((char*)NULL, ", ") == NULL);
(void)strcpy(one, ", first, ");
equal(strtok(one, ", "), "first"); /* Extra delims, 1 tok. */
check(strtok((char*)NULL, ", ") == NULL);
(void)strcpy(one, "1a, 1b; 2a, 2b");
equal(strtok(one, ", "), "1a"); /* Changing delim lists. */
equal(strtok((char*)NULL, "; "), "1b");
equal(strtok((char*)NULL, ", "), "2a");
(void)strcpy(two, "x-y");
equal(strtok(two, "-"), "x"); /* New string before done. */
equal(strtok((char*)NULL, "-"), "y");
check(strtok((char*)NULL, "-") == NULL);
(void)strcpy(one, "a,b, c,, ,d");
equal(strtok(one, ", "), "a"); /* Different separators. */
equal(strtok((char*)NULL, ", "), "b");
equal(strtok((char*)NULL, " ,"), "c"); /* Permute list too. */
equal(strtok((char*)NULL, " ,"), "d");
check(strtok((char*)NULL, ", ") == NULL);
check(strtok((char*)NULL, ", ") == NULL); /* Persistence. */
(void)strcpy(one, ", ");
check(strtok(one, ", ") == NULL); /* No tokens. */
(void)strcpy(one, "");
check(strtok(one, ", ") == NULL); /* Empty string. */
(void)strcpy(one, "abc");
equal(strtok(one, ", "), "abc"); /* No delimiters. */
check(strtok((char*)NULL, ", ") == NULL);
(void)strcpy(one, "abc");
equal(strtok(one, ""), "abc"); /* Empty delimiter list. */
check(strtok((char*)NULL, "") == NULL);
(void)strcpy(one, "abcdefgh");
(void)strcpy(one, "a,b,c");
equal(strtok(one, ","), "a"); /* Basics again... */
equal(strtok((char*)NULL, ","), "b");
equal(strtok((char*)NULL, ","), "c");
check(strtok((char*)NULL, ",") == NULL);
equal(one + 6, "gh"); /* Stomped past end? */
equal(one, "a"); /* Stomped old tokens? */
equal(one + 2, "b");
equal(one + 4, "c");
/* memcmp. */
it = "memcmp";
check(memcmp("a", "a", 1) == 0); /* Identity. */
check(memcmp("abc", "abc", 3) == 0); /* Multicharacter. */
check(memcmp("abcd", "abce", 4) < 0); /* Honestly unequal. */
check(memcmp("abce", "abcd",4));
check(memcmp("alph", "beta", 4) < 0);
check(memcmp("abce", "abcd", 3) == 0); /* Count limited. */
check(memcmp("abc", "def", 0) == 0); /* Zero count. */
/* memcmp. */
it = "memcmp";
check(memcmp("a", "a", 1) == 0); /* Identity. */
check(memcmp("abc", "abc", 3) == 0); /* Multicharacter. */
check(memcmp("abcd", "abce", 4) < 0); /* Honestly unequal. */
check(memcmp("abce", "abcd", 4));
check(memcmp("alph", "beta", 4) < 0);
check(memcmp("abce", "abcd", 3) == 0); /* Count limited. */
check(memcmp("abc", "def", 0) == 0); /* Zero count. */
/* memcmp should test strings as unsigned */
one[0] = 0xfe;
two[0] = 0x03;
check(memcmp(one, two,1) > 0);
/* memchr. */
it = "memchr";
check(memchr("abcd", 'z', 4) == NULL); /* Not found. */
(void) strcpy(one, "abcd");
check(memchr(one, 'c', 4) == one+2); /* Basic test. */
check(memchr(one, 'd', 4) == one+3); /* End of string. */
check(memchr(one, 'a', 4) == one); /* Beginning. */
check(memchr(one, '\0', 5) == one+4); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(memchr(one, 'b', 5) == one+1); /* Finding first. */
check(memchr(one, 'b', 0) == NULL); /* Zero count. */
check(memchr(one, 'a', 1) == one); /* Singleton case. */
(void) strcpy(one, "a\203b");
check(memchr(one, 0203, 3) == one+1); /* Unsignedness. */
/* memcmp should test strings as unsigned */
one[0] = 0xfe;
two[0] = 0x03;
check(memcmp(one, two, 1) > 0);
/* memcpy - need not work for overlap. */
it = "memcpy";
check(memcpy(one, "abc", 4) == one); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
/* memchr. */
it = "memchr";
check(memchr("abcd", 'z', 4) == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(memchr(one, 'c', 4) == one + 2); /* Basic test. */
check(memchr(one, 'd', 4) == one + 3); /* End of string. */
check(memchr(one, 'a', 4) == one); /* Beginning. */
check(memchr(one, '\0', 5) == one + 4); /* Finding NUL. */
(void)strcpy(one, "ababa");
check(memchr(one, 'b', 5) == one + 1); /* Finding first. */
check(memchr(one, 'b', 0) == NULL); /* Zero count. */
check(memchr(one, 'a', 1) == one); /* Singleton case. */
(void)strcpy(one, "a\203b");
check(memchr(one, 0203, 3) == one + 1); /* Unsignedness. */
(void) strcpy(one, "abcdefgh");
(void) memcpy(one+1, "xyz", 2);
equal(one, "axydefgh"); /* Basic test. */
/* memcpy - need not work for overlap. */
it = "memcpy";
check(memcpy(one, "abc", 4) == one); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
(void) strcpy(one, "abc");
(void) memcpy(one, "xyz", 0);
equal(one, "abc"); /* Zero-length copy. */
(void)strcpy(one, "abcdefgh");
(void)memcpy(one + 1, "xyz", 2);
equal(one, "axydefgh"); /* Basic test. */
(void) strcpy(one, "hi there");
(void) strcpy(two, "foo");
(void) memcpy(two, one, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
(void)strcpy(one, "abc");
(void)memcpy(one, "xyz", 0);
equal(one, "abc"); /* Zero-length copy. */
(void)strcpy(one, "hi there");
(void)strcpy(two, "foo");
(void)memcpy(two, one, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
#if 0
/* memmove - must work on overlap. */
it = "memmove";
@ -499,68 +485,69 @@ void libm_test_string()
check(memccpy(two, one, 'x', 1) == two+1); /* Singleton. */
equal(two, "xbcdlebee");
#endif
/* memset. */
it = "memset";
(void) strcpy(one, "abcdefgh");
check(memset(one+1, 'x', 3) == one+1); /* Return value. */
equal(one, "axxxefgh"); /* Basic test. */
/* memset. */
it = "memset";
(void)strcpy(one, "abcdefgh");
check(memset(one + 1, 'x', 3) == one + 1); /* Return value. */
equal(one, "axxxefgh"); /* Basic test. */
(void) memset(one+2, 'y', 0);
equal(one, "axxxefgh"); /* Zero-length set. */
(void)memset(one + 2, 'y', 0);
equal(one, "axxxefgh"); /* Zero-length set. */
(void) memset(one+5, 0, 1);
equal(one, "axxxe"); /* Zero fill. */
equal(one+6, "gh"); /* _AND the leftover. */
(void)memset(one + 5, 0, 1);
equal(one, "axxxe"); /* Zero fill. */
equal(one + 6, "gh"); /* _AND the leftover. */
(void) memset(one+2, 010045, 1);
equal(one, "ax\045xe"); /* Unsigned char convert. */
(void)memset(one + 2, 010045, 1);
equal(one, "ax\045xe"); /* Unsigned char convert. */
/* bcopy - much like memcpy.
Berklix manual is silent about overlap, so don't test it. */
it = "bcopy";
(void) bcopy("abc", one, 4);
equal(one, "abc"); /* Simple copy. */
/* bcopy - much like memcpy.
Berklix manual is silent about overlap, so don't test it. */
it = "bcopy";
(void)bcopy("abc", one, 4);
equal(one, "abc"); /* Simple copy. */
(void) strcpy(one, "abcdefgh");
(void) bcopy("xyz", one+1, 2);
equal(one, "axydefgh"); /* Basic test. */
(void)strcpy(one, "abcdefgh");
(void)bcopy("xyz", one + 1, 2);
equal(one, "axydefgh"); /* Basic test. */
(void) strcpy(one, "abc");
(void) bcopy("xyz", one, 0);
equal(one, "abc"); /* Zero-length copy. */
(void)strcpy(one, "abc");
(void)bcopy("xyz", one, 0);
equal(one, "abc"); /* Zero-length copy. */
(void) strcpy(one, "hi there");
(void) strcpy(two, "foo");
(void) bcopy(one, two, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
(void)strcpy(one, "hi there");
(void)strcpy(two, "foo");
(void)bcopy(one, two, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
/* bzero. */
it = "bzero";
(void) strcpy(one, "abcdef");
bzero(one+2, 2);
equal(one, "ab"); /* Basic test. */
equal(one+3, "");
equal(one+4, "ef");
/* bzero. */
it = "bzero";
(void)strcpy(one, "abcdef");
bzero(one + 2, 2);
equal(one, "ab"); /* Basic test. */
equal(one + 3, "");
equal(one + 4, "ef");
(void) strcpy(one, "abcdef");
bzero(one+2, 0);
equal(one, "abcdef"); /* Zero-length copy. */
(void)strcpy(one, "abcdef");
bzero(one + 2, 0);
equal(one, "abcdef"); /* Zero-length copy. */
/* bcmp - somewhat like memcmp. */
it = "bcmp";
check(bcmp("a", "a", 1) == 0); /* Identity. */
check(bcmp("abc", "abc", 3) == 0); /* Multicharacter. */
check(bcmp("abcd", "abce", 4) != 0); /* Honestly unequal. */
check(bcmp("abce", "abcd",4));
check(bcmp("alph", "beta", 4) != 0);
check(bcmp("abce", "abcd", 3) == 0); /* Count limited. */
check(bcmp("abc", "def", 0) == 0); /* Zero count. */
/* bcmp - somewhat like memcmp. */
it = "bcmp";
check(bcmp("a", "a", 1) == 0); /* Identity. */
check(bcmp("abc", "abc", 3) == 0); /* Multicharacter. */
check(bcmp("abcd", "abce", 4) != 0); /* Honestly unequal. */
check(bcmp("abce", "abcd", 4));
check(bcmp("alph", "beta", 4) != 0);
check(bcmp("abce", "abcd", 3) == 0); /* Count limited. */
check(bcmp("abc", "def", 0) == 0); /* Zero count. */
if (errors) abort();
printf("ok\n");
if (errors)
abort();
printf("ok\n");
#if 0 /* strerror - VERY system-dependent. */
#if 0 /* strerror - VERY system-dependent. */
{
extern CONST unsigned int _sys_nerr;
extern CONST char *CONST _sys_errlist[];
@ -572,4 +559,3 @@ void libm_test_string()
}
#endif
}

View File

@ -31,7 +31,6 @@
#include <stdio.h>
#include <stdarg.h>
#define memcmp memcmp_P
#define memcpy memcpy_P
#define memmem memmem_P
@ -69,106 +68,105 @@
#define TOO_MANY_ERRORS 11
static int errors = 0;
static void
print_error (char const* msg, ...)
{
errors++;
if (errors == TOO_MANY_ERRORS)
static void print_error(char const* msg, ...)
{
errors++;
if (errors == TOO_MANY_ERRORS)
{
fprintf (stderr, "Too many errors.\n");
fprintf(stderr, "Too many errors.\n");
}
else if (errors < TOO_MANY_ERRORS)
else if (errors < TOO_MANY_ERRORS)
{
va_list ap;
va_start (ap, msg);
vfprintf (stderr, msg, ap);
va_end (ap);
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
}
else
else
{
/* Further errors omitted. */
/* Further errors omitted. */
}
}
extern int rand_seed;
void memcpy_main(void)
void memcpy_main(void)
{
/* Allocate buffers to read and write from. */
char src[BUFF_SIZE], dest[BUFF_SIZE], backup_src[BUFF_SIZE];
/* Allocate buffers to read and write from. */
char src[BUFF_SIZE], dest[BUFF_SIZE], backup_src[BUFF_SIZE];
/* Fill the source buffer with non-null values, reproducible random data. */
srand (rand_seed);
int i, j;
unsigned sa;
unsigned da;
unsigned n;
for (i = 0; i < BUFF_SIZE; i++)
/* Fill the source buffer with non-null values, reproducible random data. */
srand(rand_seed);
int i, j;
unsigned sa;
unsigned da;
unsigned n;
for (i = 0; i < BUFF_SIZE; i++)
{
src[i] = (char)rand () | 1;
backup_src[i] = src[i];
src[i] = (char)rand() | 1;
backup_src[i] = src[i];
}
/* Make calls to memcpy with block sizes ranging between 1 and
MAX_BLOCK_SIZE bytes, aligned and misaligned source and destination. */
for (sa = 0; sa <= MAX_OFFSET; sa++)
for (da = 0; da <= MAX_OFFSET; da++)
for (n = 1; n <= MAX_BLOCK_SIZE; n++)
{
//printf (".");
/* Zero dest so we can check it properly after the copying. */
for (j = 0; j < BUFF_SIZE; j++)
dest[j] = 0;
void *ret = memcpy (dest + START_COPY + da, src + sa, n);
/* Check return value. */
if (ret != (dest + START_COPY + da))
print_error ("\nFailed: wrong return value in memcpy of %u bytes "
"with src_align %u and dst_align %u. "
"Return value and dest should be the same"
"(ret is %p, dest is %p)\n",
n, sa, da, ret, dest + START_COPY + da);
/* Check that content of the destination buffer
is the same as the source buffer, and
memory outside destination buffer is not modified. */
for (j = 0; j < BUFF_SIZE; j++)
if ((unsigned)j < START_COPY + da)
{
if (dest[j] != 0)
print_error ("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u before the start of dest is not 0.\n",
n, sa, da, START_COPY - j);
}
else if ((unsigned)j < START_COPY + da + n)
{
i = j - START_COPY - da;
if (dest[j] != (src + sa)[i])
print_error ("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u in dest and src are not the same.\n",
n, sa, da, i);
}
else if (dest[j] != 0)
{
print_error ("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u after the end of dest is not 0.\n",
n, sa, da, j - START_COPY - da - n);
}
/* Make calls to memcpy with block sizes ranging between 1 and
MAX_BLOCK_SIZE bytes, aligned and misaligned source and destination. */
for (sa = 0; sa <= MAX_OFFSET; sa++)
for (da = 0; da <= MAX_OFFSET; da++)
for (n = 1; n <= MAX_BLOCK_SIZE; n++)
{
// printf (".");
/* Zero dest so we can check it properly after the copying. */
for (j = 0; j < BUFF_SIZE; j++)
dest[j] = 0;
/* Check src is not modified. */
for (j = 0; j < BUFF_SIZE; j++)
if (src[i] != backup_src[i])
print_error ("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u of src is modified.\n",
n, sa, da, j);
}
void* ret = memcpy(dest + START_COPY + da, src + sa, n);
if (errors != 0)
abort ();
/* Check return value. */
if (ret != (dest + START_COPY + da))
print_error("\nFailed: wrong return value in memcpy of %u bytes "
"with src_align %u and dst_align %u. "
"Return value and dest should be the same"
"(ret is %p, dest is %p)\n",
n, sa, da, ret, dest + START_COPY + da);
printf("ok\n");
/* Check that content of the destination buffer
is the same as the source buffer, and
memory outside destination buffer is not modified. */
for (j = 0; j < BUFF_SIZE; j++)
if ((unsigned)j < START_COPY + da)
{
if (dest[j] != 0)
print_error("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u before the start of dest is not 0.\n",
n, sa, da, START_COPY - j);
}
else if ((unsigned)j < START_COPY + da + n)
{
i = j - START_COPY - da;
if (dest[j] != (src + sa)[i])
print_error("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u in dest and src are not the same.\n",
n, sa, da, i);
}
else if (dest[j] != 0)
{
print_error("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u after the end of dest is not 0.\n",
n, sa, da, j - START_COPY - da - n);
}
/* Check src is not modified. */
for (j = 0; j < BUFF_SIZE; j++)
if (src[i] != backup_src[i])
print_error("\nFailed: after memcpy of %u bytes "
"with src_align %u and dst_align %u, "
"byte %u of src is modified.\n",
n, sa, da, j);
}
if (errors != 0)
abort();
printf("ok\n");
}

View File

@ -55,140 +55,132 @@
#define TOO_MANY_ERRORS 11
int errors = 0;
#define DEBUGP \
if (errors == TOO_MANY_ERRORS) \
printf ("Further errors omitted\n"); \
else if (errors < TOO_MANY_ERRORS) \
printf
#define DEBUGP \
if (errors == TOO_MANY_ERRORS) \
printf("Further errors omitted\n"); \
else if (errors < TOO_MANY_ERRORS) \
printf
/* A safe target-independent memmove. */
void
mymemmove (unsigned char *dest, unsigned char *src, size_t n)
void mymemmove(unsigned char* dest, unsigned char* src, size_t n)
{
if ((src <= dest && src + n <= dest)
|| src >= dest)
while (n-- > 0)
*dest++ = *src++;
else
if ((src <= dest && src + n <= dest) || src >= dest)
while (n-- > 0)
*dest++ = *src++;
else
{
dest += n;
src += n;
while (n-- > 0)
*--dest = *--src;
dest += n;
src += n;
while (n-- > 0)
*--dest = *--src;
}
}
/* It's either the noinline attribute or forcing the test framework to
pass -fno-builtin-memmove. */
void
xmemmove (unsigned char *dest, unsigned char *src, size_t n)
__attribute__ ((__noinline__));
void xmemmove(unsigned char* dest, unsigned char* src, size_t n) __attribute__((__noinline__));
void
xmemmove (unsigned char *dest, unsigned char *src, size_t n)
void xmemmove(unsigned char* dest, unsigned char* src, size_t n)
{
void *retp;
retp = memmove (dest, src, n);
void* retp;
retp = memmove(dest, src, n);
if (retp != dest)
if (retp != dest)
{
errors++;
DEBUGP ("memmove of n bytes returned %p instead of dest=%p\n",
retp, dest);
errors++;
DEBUGP("memmove of n bytes returned %p instead of dest=%p\n", retp, dest);
}
}
/* Fill the array with something we can associate with a position, but
not exactly the same as the position index. */
void
fill (unsigned char dest[MAX*3])
void fill(unsigned char dest[MAX * 3])
{
size_t i;
for (i = 0; i < MAX*3; i++)
dest[i] = (10 + i) % MAX;
size_t i;
for (i = 0; i < MAX * 3; i++)
dest[i] = (10 + i) % MAX;
}
void memmove_main(void)
{
size_t i;
int errors = 0;
size_t i;
int errors = 0;
/* Leave some room before and after the area tested, so we can detect
overwrites of up to N bytes, N being the amount tested. If you
want to test using valgrind, make these malloced instead. */
unsigned char from_test[MAX*3];
unsigned char to_test[MAX*3];
unsigned char from_known[MAX*3];
unsigned char to_known[MAX*3];
/* Leave some room before and after the area tested, so we can detect
overwrites of up to N bytes, N being the amount tested. If you
want to test using valgrind, make these malloced instead. */
unsigned char from_test[MAX * 3];
unsigned char to_test[MAX * 3];
unsigned char from_known[MAX * 3];
unsigned char to_known[MAX * 3];
/* Non-overlap. */
for (i = 0; i < MAX; i++)
/* Non-overlap. */
for (i = 0; i < MAX; i++)
{
/* Do the memmove first before setting the known array, so we know
it didn't change any of the known array. */
fill (from_test);
fill (to_test);
xmemmove (to_test + MAX, 1 + from_test + MAX, i);
/* Do the memmove first before setting the known array, so we know
it didn't change any of the known array. */
fill(from_test);
fill(to_test);
xmemmove(to_test + MAX, 1 + from_test + MAX, i);
fill (from_known);
fill (to_known);
mymemmove (to_known + MAX, 1 + from_known + MAX, i);
fill(from_known);
fill(to_known);
mymemmove(to_known + MAX, 1 + from_known + MAX, i);
if (memcmp (to_known, to_test, sizeof (to_known)) != 0)
{
errors++;
DEBUGP ("memmove failed non-overlap test for %d bytes\n", i);
}
if (memcmp(to_known, to_test, sizeof(to_known)) != 0)
{
errors++;
DEBUGP("memmove failed non-overlap test for %d bytes\n", i);
}
}
/* Overlap-from-before. */
for (i = 0; i < MAX; i++)
/* Overlap-from-before. */
for (i = 0; i < MAX; i++)
{
size_t j;
for (j = 0; j < i; j++)
{
fill (to_test);
xmemmove (to_test + MAX * 2 - i, to_test + MAX * 2 - i - j, i);
size_t j;
for (j = 0; j < i; j++)
{
fill(to_test);
xmemmove(to_test + MAX * 2 - i, to_test + MAX * 2 - i - j, i);
fill (to_known);
mymemmove (to_known + MAX * 2 - i, to_known + MAX * 2 - i - j, i);
fill(to_known);
mymemmove(to_known + MAX * 2 - i, to_known + MAX * 2 - i - j, i);
if (memcmp (to_known, to_test, sizeof (to_known)) != 0)
{
errors++;
DEBUGP ("memmove failed for %d bytes,"
" with src %d bytes before dest\n",
i, j);
}
}
if (memcmp(to_known, to_test, sizeof(to_known)) != 0)
{
errors++;
DEBUGP("memmove failed for %d bytes,"
" with src %d bytes before dest\n",
i, j);
}
}
}
/* Overlap-from-after. */
for (i = 0; i < MAX; i++)
/* Overlap-from-after. */
for (i = 0; i < MAX; i++)
{
size_t j;
for (j = 0; j < i; j++)
{
fill (to_test);
xmemmove (to_test + MAX, to_test + MAX + j, i);
size_t j;
for (j = 0; j < i; j++)
{
fill(to_test);
xmemmove(to_test + MAX, to_test + MAX + j, i);
fill (to_known);
mymemmove (to_known + MAX, to_known + MAX + j, i);
fill(to_known);
mymemmove(to_known + MAX, to_known + MAX + j, i);
if (memcmp (to_known, to_test, sizeof (to_known)) != 0)
{
errors++;
DEBUGP ("memmove failed when moving %d bytes,"
" with src %d bytes after dest\n",
i, j);
}
}
if (memcmp(to_known, to_test, sizeof(to_known)) != 0)
{
errors++;
DEBUGP("memmove failed when moving %d bytes,"
" with src %d bytes after dest\n",
i, j);
}
}
}
if (errors != 0)
abort ();
printf("ok\n");
if (errors != 0)
abort();
printf("ok\n");
}

View File

@ -46,7 +46,6 @@
#define BUFF_SIZE 256
/* The macro LONG_TEST controls whether a short or a more comprehensive test
of strcmp should be performed. */
#ifdef LONG_TEST
@ -106,186 +105,183 @@
#error "Buffer overrun: MAX_OFFSET + MAX_BLOCK_SIZE + MAX_DIFF + MAX_LEN + MAX_ZEROS >= BUFF_SIZE."
#endif
#define TOO_MANY_ERRORS 11
static int errors = 0;
const char *testname = "strcmp";
const char* testname = "strcmp";
static void
print_error (char const* msg, ...)
static void print_error(char const* msg, ...)
{
errors++;
if (errors == TOO_MANY_ERRORS)
errors++;
if (errors == TOO_MANY_ERRORS)
{
fprintf (stderr, "Too many errors.\n");
fprintf(stderr, "Too many errors.\n");
}
else if (errors < TOO_MANY_ERRORS)
else if (errors < TOO_MANY_ERRORS)
{
va_list ap;
va_start (ap, msg);
vfprintf (stderr, msg, ap);
va_end (ap);
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
}
else
else
{
/* Further errors omitted. */
/* Further errors omitted. */
}
}
extern int rand_seed;
void strcmp_main(void)
void strcmp_main(void)
{
/* Allocate buffers to read and write from. */
char src[BUFF_SIZE], dest[BUFF_SIZE];
/* Allocate buffers to read and write from. */
char src[BUFF_SIZE], dest[BUFF_SIZE];
/* Fill the source buffer with non-null values, reproducible random data. */
srand (rand_seed);
int i, j, zeros;
unsigned sa;
unsigned da;
unsigned n, m, len;
char *p;
int ret;
/* Fill the source buffer with non-null values, reproducible random data. */
srand(rand_seed);
int i, j, zeros;
unsigned sa;
unsigned da;
unsigned n, m, len;
char* p;
int ret;
/* Make calls to strcmp with block sizes ranging between 1 and
MAX_BLOCK_SIZE bytes, aligned and misaligned source and destination. */
for (sa = 0; sa <= MAX_OFFSET; sa++)
for (da = 0; da <= MAX_OFFSET; da++)
for (n = 1; n <= MAX_BLOCK_SIZE; n++)
{
for (m = 1; m < n + MAX_DIFF; m++)
for (len = 0; len < MAX_LEN; len++)
for (zeros = 1; zeros < MAX_ZEROS; zeros++)
{
if (n - m > MAX_DIFF)
continue;
/* Make a copy of the source. */
for (i = 0; i < BUFF_SIZE; i++)
{
src[i] = 'A' + (i % 26);
dest[i] = src[i];
}
delay(0);
memcpy (dest + da, src + sa, n);
/* Make calls to strcmp with block sizes ranging between 1 and
MAX_BLOCK_SIZE bytes, aligned and misaligned source and destination. */
for (sa = 0; sa <= MAX_OFFSET; sa++)
for (da = 0; da <= MAX_OFFSET; da++)
for (n = 1; n <= MAX_BLOCK_SIZE; n++)
{
for (m = 1; m < n + MAX_DIFF; m++)
for (len = 0; len < MAX_LEN; len++)
for (zeros = 1; zeros < MAX_ZEROS; zeros++)
{
if (n - m > MAX_DIFF)
continue;
/* Make a copy of the source. */
for (i = 0; i < BUFF_SIZE; i++)
{
src[i] = 'A' + (i % 26);
dest[i] = src[i];
}
delay(0);
memcpy(dest + da, src + sa, n);
/* Make src 0-terminated. */
p = src + sa + n - 1;
for (i = 0; i < zeros; i++)
{
*p++ = '\0';
}
/* Make src 0-terminated. */
p = src + sa + n - 1;
for (i = 0; i < zeros; i++)
{
*p++ = '\0';
}
/* Modify dest. */
p = dest + da + m - 1;
for (j = 0; j < (int)len; j++)
*p++ = 'x';
/* Make dest 0-terminated. */
*p = '\0';
/* Modify dest. */
p = dest + da + m - 1;
for (j = 0; j < (int)len; j++)
*p++ = 'x';
/* Make dest 0-terminated. */
*p = '\0';
ret = strcmp (src + sa, dest + da);
ret = strcmp(src + sa, dest + da);
/* Check return value. */
if (n == m)
{
if (len == 0)
{
if (ret != 0)
{
print_error ("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected 0.\n",
testname, n, sa, da, m, len, ret);
}
}
else
{
if (ret >= 0)
print_error ("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected negative.\n",
testname, n, sa, da, m, len, ret);
}
}
else if (m > n)
{
if (ret >= 0)
{
print_error ("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected negative.\n",
testname, n, sa, da, m, len, ret);
}
}
else /* m < n */
{
if (len == 0)
{
if (ret <= 0)
print_error ("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected positive.\n",
testname, n, sa, da, m, len, ret);
}
else
{
if (ret >= 0)
print_error ("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected negative.\n",
testname, n, sa, da, m, len, ret);
}
}
}
}
/* Check return value. */
if (n == m)
{
if (len == 0)
{
if (ret != 0)
{
print_error("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected 0.\n",
testname, n, sa, da, m, len, ret);
}
}
else
{
if (ret >= 0)
print_error("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected negative.\n",
testname, n, sa, da, m, len, ret);
}
}
else if (m > n)
{
if (ret >= 0)
{
print_error("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected negative.\n",
testname, n, sa, da, m, len, ret);
}
}
else /* m < n */
{
if (len == 0)
{
if (ret <= 0)
print_error("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected positive.\n",
testname, n, sa, da, m, len, ret);
}
else
{
if (ret >= 0)
print_error("\nFailed: after %s of %u bytes "
"with src_align %u and dst_align %u, "
"dest after %d bytes is modified for %d bytes, "
"return value is %d, expected negative.\n",
testname, n, sa, da, m, len, ret);
}
}
}
}
/* Check some corner cases. */
src[1] = 'A';
dest[1] = 'A';
src[2] = 'B';
dest[2] = 'B';
src[3] = 'C';
dest[3] = 'C';
src[4] = '\0';
dest[4] = '\0';
/* Check some corner cases. */
src[1] = 'A';
dest[1] = 'A';
src[2] = 'B';
dest[2] = 'B';
src[3] = 'C';
dest[3] = 'C';
src[4] = '\0';
dest[4] = '\0';
src[0] = 0xc1;
dest[0] = 0x41;
ret = strcmp (src, dest);
if (ret <= 0)
print_error ("\nFailed: expected positive, return %d\n", ret);
src[0] = 0xc1;
dest[0] = 0x41;
ret = strcmp(src, dest);
if (ret <= 0)
print_error("\nFailed: expected positive, return %d\n", ret);
src[0] = 0x01;
dest[0] = 0x82;
ret = strcmp (src, dest);
if (ret >= 0)
print_error ("\nFailed: expected negative, return %d\n", ret);
src[0] = 0x01;
dest[0] = 0x82;
ret = strcmp(src, dest);
if (ret >= 0)
print_error("\nFailed: expected negative, return %d\n", ret);
dest[0] = src[0] = 'D';
src[3] = 0xc1;
dest[3] = 0x41;
ret = strcmp (src, dest);
if (ret <= 0)
print_error ("\nFailed: expected positive, return %d\n", ret);
dest[0] = src[0] = 'D';
src[3] = 0xc1;
dest[3] = 0x41;
ret = strcmp(src, dest);
if (ret <= 0)
print_error("\nFailed: expected positive, return %d\n", ret);
src[3] = 0x01;
dest[3] = 0x82;
ret = strcmp (src, dest);
if (ret >= 0)
print_error ("\nFailed: expected negative, return %d\n", ret);
src[3] = 0x01;
dest[3] = 0x82;
ret = strcmp(src, dest);
if (ret >= 0)
print_error("\nFailed: expected negative, return %d\n", ret);
//printf ("\n");
if (errors != 0)
// printf ("\n");
if (errors != 0)
{
printf ("ERROR. FAILED.\n");
abort ();
printf("ERROR. FAILED.\n");
abort();
}
//exit (0);
printf("ok\n");
// exit (0);
printf("ok\n");
}

View File

@ -26,336 +26,297 @@
#define MAX_2 (2 * MAX_1 + MAX_1 / 10)
void eprintf (int line, char *result, char *expected, int size)
void eprintf(int line, char* result, char* expected, int size)
{
if (size != 0)
printf ("Failure at line %d, result is <%.*s>, should be <%s> of size %d\n",
line, size, result, expected, size);
else
printf ("Failure at line %d, result is <%s>, should be <%s>\n",
line, result, expected);
if (size != 0)
printf("Failure at line %d, result is <%.*s>, should be <%s> of size %d\n", line, size,
result, expected, size);
else
printf("Failure at line %d, result is <%s>, should be <%s>\n", line, result, expected);
}
void mycopy (char *target, char *source, int size)
void mycopy(char* target, char* source, int size)
{
int i;
int i;
for (i = 0; i < size; ++i)
for (i = 0; i < size; ++i)
{
target[i] = source[i];
target[i] = source[i];
}
}
void myset (char *target, char ch, int size)
void myset(char* target, char ch, int size)
{
int i;
for (i = 0; i < size; ++i)
int i;
for (i = 0; i < size; ++i)
{
target[i] = ch;
target[i] = ch;
}
}
void tstring_main(void)
{
char target[MAX_1] = "A";
char first_char;
char second_char;
char array[] = "abcdefghijklmnopqrstuvwxz";
char array2[] = "0123456789!@#$%^&*(";
char buffer2[MAX_1];
char buffer3[MAX_1];
char buffer4[MAX_1];
char buffer5[MAX_2];
char buffer6[MAX_2];
char buffer7[MAX_2];
char expected[MAX_1];
char *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7;
int i, j, k, x, z, align_test_iterations;
z = 0;
int test_failed = 0;
char target[MAX_1] = "A";
char first_char;
char second_char;
char array[] = "abcdefghijklmnopqrstuvwxz";
char array2[] = "0123456789!@#$%^&*(";
char buffer2[MAX_1];
char buffer3[MAX_1];
char buffer4[MAX_1];
char buffer5[MAX_2];
char buffer6[MAX_2];
char buffer7[MAX_2];
char expected[MAX_1];
char *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7;
int i, j, k, x, z, align_test_iterations;
z = 0;
tmp1 = target;
tmp2 = buffer2;
tmp3 = buffer3;
tmp4 = buffer4;
tmp5 = buffer5;
tmp6 = buffer6;
tmp7 = buffer7;
int test_failed = 0;
tmp2[0] = 'Z';
tmp2[1] = '\0';
tmp1 = target;
tmp2 = buffer2;
tmp3 = buffer3;
tmp4 = buffer4;
tmp5 = buffer5;
tmp6 = buffer6;
tmp7 = buffer7;
if (memset (target, 'X', 0) != target ||
memcpy (target, "Y", 0) != target ||
memmove (target, "K", 0) != target ||
strncpy (tmp2, "4", 0) != tmp2 ||
strncat (tmp2, "123", 0) != tmp2 ||
strcat (target, "") != target)
tmp2[0] = 'Z';
tmp2[1] = '\0';
if (memset(target, 'X', 0) != target || memcpy(target, "Y", 0) != target
|| memmove(target, "K", 0) != target || strncpy(tmp2, "4", 0) != tmp2
|| strncat(tmp2, "123", 0) != tmp2 || strcat(target, "") != target)
{
eprintf (__LINE__, target, "A", 0);
test_failed = 1;
eprintf(__LINE__, target, "A", 0);
test_failed = 1;
}
if (strcmp (target, "A") || strlen(target) != 1 || memchr (target, 'A', 0) != NULL
|| memcmp (target, "J", 0) || strncmp (target, "A", 1) || strncmp (target, "J", 0) ||
tmp2[0] != 'Z' || tmp2[1] != '\0')
if (strcmp(target, "A") || strlen(target) != 1 || memchr(target, 'A', 0) != NULL
|| memcmp(target, "J", 0) || strncmp(target, "A", 1) || strncmp(target, "J", 0)
|| tmp2[0] != 'Z' || tmp2[1] != '\0')
{
eprintf (__LINE__, target, "A", 0);
test_failed = 1;
eprintf(__LINE__, target, "A", 0);
test_failed = 1;
}
tmp2[2] = 'A';
if (strcpy (target, "") != target ||
strncpy (tmp2, "", 4) != tmp2 ||
strcat (target, "") != target)
tmp2[2] = 'A';
if (strcpy(target, "") != target || strncpy(tmp2, "", 4) != tmp2
|| strcat(target, "") != target)
{
eprintf (__LINE__, target, "", 0);
test_failed = 1;
eprintf(__LINE__, target, "", 0);
test_failed = 1;
}
if (target[0] != '\0' || strncmp (target, "", 1) ||
memcmp (tmp2, "\0\0\0\0", 4))
if (target[0] != '\0' || strncmp(target, "", 1) || memcmp(tmp2, "\0\0\0\0", 4))
{
eprintf (__LINE__, target, "", 0);
test_failed = 1;
eprintf(__LINE__, target, "", 0);
test_failed = 1;
}
tmp2[2] = 'A';
if (strncat (tmp2, "1", 3) != tmp2 ||
memcmp (tmp2, "1\0A", 3))
tmp2[2] = 'A';
if (strncat(tmp2, "1", 3) != tmp2 || memcmp(tmp2, "1\0A", 3))
{
eprintf (__LINE__, tmp2, "1\0A", 3);
test_failed = 1;
eprintf(__LINE__, tmp2, "1\0A", 3);
test_failed = 1;
}
if (strcpy (tmp3, target) != tmp3 ||
strcat (tmp3, "X") != tmp3 ||
strncpy (tmp2, "X", 2) != tmp2 ||
memset (target, tmp2[0], 1) != target)
if (strcpy(tmp3, target) != tmp3 || strcat(tmp3, "X") != tmp3 || strncpy(tmp2, "X", 2) != tmp2
|| memset(target, tmp2[0], 1) != target)
{
eprintf (__LINE__, target, "X", 0);
test_failed = 1;
eprintf(__LINE__, target, "X", 0);
test_failed = 1;
}
if (strcmp (target, "X") || strlen (target) != 1 ||
memchr (target, 'X', 2) != target ||
strchr (target, 'X') != target ||
memchr (target, 'Y', 2) != NULL ||
strchr (target, 'Y') != NULL ||
strcmp (tmp3, target) ||
strncmp (tmp3, target, 2) ||
memcmp (target, "K", 0) ||
strncmp (target, tmp3, 3))
if (strcmp(target, "X") || strlen(target) != 1 || memchr(target, 'X', 2) != target
|| strchr(target, 'X') != target || memchr(target, 'Y', 2) != NULL
|| strchr(target, 'Y') != NULL || strcmp(tmp3, target) || strncmp(tmp3, target, 2)
|| memcmp(target, "K", 0) || strncmp(target, tmp3, 3))
{
eprintf (__LINE__, target, "X", 0);
test_failed = 1;
eprintf(__LINE__, target, "X", 0);
test_failed = 1;
}
if (strcpy (tmp3, "Y") != tmp3 ||
strcat (tmp3, "Y") != tmp3 ||
memset (target, 'Y', 2) != target)
if (strcpy(tmp3, "Y") != tmp3 || strcat(tmp3, "Y") != tmp3 || memset(target, 'Y', 2) != target)
{
eprintf (__LINE__, target, "Y", 0);
test_failed = 1;
eprintf(__LINE__, target, "Y", 0);
test_failed = 1;
}
target[2] = '\0';
if (memcmp (target, "YY", 2) || strcmp (target, "YY") ||
strlen (target) != 2 || memchr (target, 'Y', 2) != target ||
strcmp (tmp3, target) ||
strncmp (target, tmp3, 3) ||
strncmp (target, tmp3, 4) ||
strncmp (target, tmp3, 2) ||
strchr (target, 'Y') != target)
target[2] = '\0';
if (memcmp(target, "YY", 2) || strcmp(target, "YY") || strlen(target) != 2
|| memchr(target, 'Y', 2) != target || strcmp(tmp3, target) || strncmp(target, tmp3, 3)
|| strncmp(target, tmp3, 4) || strncmp(target, tmp3, 2) || strchr(target, 'Y') != target)
{
eprintf (__LINE__, target, "YY", 2);
test_failed = 1;
eprintf(__LINE__, target, "YY", 2);
test_failed = 1;
}
strcpy (target, "WW");
if (memcmp (target, "WW", 2) || strcmp (target, "WW") ||
strlen (target) != 2 || memchr (target, 'W', 2) != target ||
strchr (target, 'W') != target)
strcpy(target, "WW");
if (memcmp(target, "WW", 2) || strcmp(target, "WW") || strlen(target) != 2
|| memchr(target, 'W', 2) != target || strchr(target, 'W') != target)
{
eprintf (__LINE__, target, "WW", 2);
test_failed = 1;
eprintf(__LINE__, target, "WW", 2);
test_failed = 1;
}
if (strncpy (target, "XX", 16) != target ||
memcmp (target, "XX\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
if (strncpy(target, "XX", 16) != target || memcmp(target, "XX\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
{
eprintf (__LINE__, target, "XX\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
test_failed = 1;
eprintf(__LINE__, target, "XX\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
test_failed = 1;
}
if (strcpy (tmp3, "ZZ") != tmp3 ||
strcat (tmp3, "Z") != tmp3 ||
memcpy (tmp4, "Z", 2) != tmp4 ||
strcat (tmp4, "ZZ") != tmp4 ||
memset (target, 'Z', 3) != target)
if (strcpy(tmp3, "ZZ") != tmp3 || strcat(tmp3, "Z") != tmp3 || memcpy(tmp4, "Z", 2) != tmp4
|| strcat(tmp4, "ZZ") != tmp4 || memset(target, 'Z', 3) != target)
{
eprintf (__LINE__, target, "ZZZ", 3);
test_failed = 1;
eprintf(__LINE__, target, "ZZZ", 3);
test_failed = 1;
}
target[3] = '\0';
tmp5[0] = '\0';
strncat (tmp5, "123", 2);
if (memcmp (target, "ZZZ", 3) || strcmp (target, "ZZZ") ||
strcmp (tmp3, target) || strcmp (tmp4, target) ||
strncmp (target, "ZZZ", 4) || strncmp (target, "ZZY", 3) <= 0 ||
strncmp ("ZZY", target, 4) >= 0 ||
memcmp (tmp5, "12", 3) ||
strlen (target) != 3)
target[3] = '\0';
tmp5[0] = '\0';
strncat(tmp5, "123", 2);
if (memcmp(target, "ZZZ", 3) || strcmp(target, "ZZZ") || strcmp(tmp3, target)
|| strcmp(tmp4, target) || strncmp(target, "ZZZ", 4) || strncmp(target, "ZZY", 3) <= 0
|| strncmp("ZZY", target, 4) >= 0 || memcmp(tmp5, "12", 3) || strlen(target) != 3)
{
eprintf (__LINE__, target, "ZZZ", 3);
test_failed = 1;
eprintf(__LINE__, target, "ZZZ", 3);
test_failed = 1;
}
target[2] = 'K';
if (memcmp (target, "ZZZ", 2) || strcmp (target, "ZZZ") >= 0 ||
memcmp (target, "ZZZ", 3) >= 0 || strlen (target) != 3 ||
memchr (target, 'K', 3) != target + 2 ||
strncmp (target, "ZZZ", 2) || strncmp (target, "ZZZ", 4) >= 0 ||
strchr (target, 'K') != target + 2)
target[2] = 'K';
if (memcmp(target, "ZZZ", 2) || strcmp(target, "ZZZ") >= 0 || memcmp(target, "ZZZ", 3) >= 0
|| strlen(target) != 3 || memchr(target, 'K', 3) != target + 2 || strncmp(target, "ZZZ", 2)
|| strncmp(target, "ZZZ", 4) >= 0 || strchr(target, 'K') != target + 2)
{
eprintf (__LINE__, target, "ZZK", 3);
test_failed = 1;
eprintf(__LINE__, target, "ZZK", 3);
test_failed = 1;
}
strcpy (target, "AAA");
if (memcmp (target, "AAA", 3) || strcmp (target, "AAA") ||
strncmp (target, "AAA", 3) ||
strlen (target) != 3)
strcpy(target, "AAA");
if (memcmp(target, "AAA", 3) || strcmp(target, "AAA") || strncmp(target, "AAA", 3)
|| strlen(target) != 3)
{
eprintf (__LINE__, target, "AAA", 3);
test_failed = 1;
eprintf(__LINE__, target, "AAA", 3);
test_failed = 1;
}
j = 5;
while (j < MAX_1)
j = 5;
while (j < MAX_1)
{
for (i = j-1; i <= j+1; ++i)
for (i = j - 1; i <= j + 1; ++i)
{
/* don't bother checking unaligned data in the larger
sizes since it will waste time without performing additional testing */
if ((size_t)i <= 16 * sizeof(long))
{
align_test_iterations = 2*sizeof(long);
if ((size_t)i <= 2 * sizeof(long) + 1)
z = 2;
else
z = 2 * sizeof(long);
}
else
/* don't bother checking unaligned data in the larger
sizes since it will waste time without performing additional testing */
if ((size_t)i <= 16 * sizeof(long))
{
align_test_iterations = 1;
align_test_iterations = 2 * sizeof(long);
if ((size_t)i <= 2 * sizeof(long) + 1)
z = 2;
else
z = 2 * sizeof(long);
}
else
{
align_test_iterations = 1;
}
for (x = 0; x < align_test_iterations; ++x)
{
tmp1 = target + x;
tmp2 = buffer2 + x;
tmp3 = buffer3 + x;
tmp4 = buffer4 + x;
tmp5 = buffer5 + x;
tmp6 = buffer6 + x;
for (x = 0; x < align_test_iterations; ++x)
{
tmp1 = target + x;
tmp2 = buffer2 + x;
tmp3 = buffer3 + x;
tmp4 = buffer4 + x;
tmp5 = buffer5 + x;
tmp6 = buffer6 + x;
first_char = array[i % (sizeof(array) - 1)];
second_char = array2[i % (sizeof(array2) - 1)];
memset (tmp1, first_char, i);
mycopy (tmp2, tmp1, i);
myset (tmp2 + z, second_char, i - z - 1);
if (memcpy (tmp1 + z, tmp2 + z, i - z - 1) != tmp1 + z)
{
printf ("error at line %d\n", __LINE__);
test_failed = 1;
}
first_char = array[i % (sizeof(array) - 1)];
second_char = array2[i % (sizeof(array2) - 1)];
memset(tmp1, first_char, i);
mycopy(tmp2, tmp1, i);
myset(tmp2 + z, second_char, i - z - 1);
if (memcpy(tmp1 + z, tmp2 + z, i - z - 1) != tmp1 + z)
{
printf("error at line %d\n", __LINE__);
test_failed = 1;
}
tmp1[i] = '\0';
tmp2[i] = '\0';
if (strcpy (expected, tmp2) != expected)
{
printf ("error at line %d\n", __LINE__);
test_failed = 1;
}
tmp2[i-z] = first_char + 1;
if (memmove (tmp2 + z + 1, tmp2 + z, i - z - 1) != tmp2 + z + 1 ||
memset (tmp3, first_char, i) != tmp3)
{
printf ("error at line %d\n", __LINE__);
test_failed = 1;
}
tmp1[i] = '\0';
tmp2[i] = '\0';
if (strcpy(expected, tmp2) != expected)
{
printf("error at line %d\n", __LINE__);
test_failed = 1;
}
tmp2[i - z] = first_char + 1;
if (memmove(tmp2 + z + 1, tmp2 + z, i - z - 1) != tmp2 + z + 1
|| memset(tmp3, first_char, i) != tmp3)
{
printf("error at line %d\n", __LINE__);
test_failed = 1;
}
myset (tmp4, first_char, i);
tmp5[0] = '\0';
if (strncpy (tmp5, tmp1, i+1) != tmp5 ||
strcat (tmp5, tmp1) != tmp5)
{
printf ("error at line %d\n", __LINE__);
test_failed = 1;
}
mycopy (tmp6, tmp1, i);
mycopy (tmp6 + i, tmp1, i + 1);
myset(tmp4, first_char, i);
tmp5[0] = '\0';
if (strncpy(tmp5, tmp1, i + 1) != tmp5 || strcat(tmp5, tmp1) != tmp5)
{
printf("error at line %d\n", __LINE__);
test_failed = 1;
}
mycopy(tmp6, tmp1, i);
mycopy(tmp6 + i, tmp1, i + 1);
tmp7[2*i+z] = second_char;
strcpy (tmp7, tmp1);
(void)strchr (tmp1, second_char);
if (memcmp (tmp1, expected, i) || strcmp (tmp1, expected) ||
strncmp (tmp1, expected, i) ||
strncmp (tmp1, expected, i+1) ||
strcmp (tmp1, tmp2) >= 0 || memcmp (tmp1, tmp2, i) >= 0 ||
strncmp (tmp1, tmp2, i+1) >= 0 ||
(int)strlen (tmp1) != i || memchr (tmp1, first_char, i) != tmp1 ||
strchr (tmp1, first_char) != tmp1 ||
memchr (tmp1, second_char, i) != tmp1 + z ||
strchr (tmp1, second_char) != tmp1 + z ||
strcmp (tmp5, tmp6) ||
strncat (tmp7, tmp1, i+2) != tmp7 ||
strcmp (tmp7, tmp6) ||
tmp7[2*i+z] != second_char)
{
eprintf (__LINE__, tmp1, expected, 0);
printf ("x is %d\n",x);
printf ("i is %d\n", i);
printf ("tmp1 is <%p>\n", tmp1);
printf ("tmp5 is <%p> <%s>\n", tmp5, tmp5);
printf ("tmp6 is <%p> <%s>\n", tmp6, tmp6);
test_failed = 1;
}
tmp7[2 * i + z] = second_char;
strcpy(tmp7, tmp1);
for (k = 1; k <= align_test_iterations && k <= i; ++k)
{
if (memcmp (tmp3, tmp4, i - k + 1) != 0 ||
strncmp (tmp3, tmp4, i - k + 1) != 0)
{
printf ("Failure at line %d, comparing %.*s with %.*s\n",
__LINE__, i, tmp3, i, tmp4);
test_failed = 1;
}
tmp4[i-k] = first_char + 1;
if (memcmp (tmp3, tmp4, i) >= 0 ||
strncmp (tmp3, tmp4, i) >= 0 ||
memcmp (tmp4, tmp3, i) <= 0 ||
strncmp (tmp4, tmp3, i) <= 0)
{
printf ("Failure at line %d, comparing %.*s with %.*s\n",
__LINE__, i, tmp3, i, tmp4);
test_failed = 1;
}
tmp4[i-k] = first_char;
}
}
(void)strchr(tmp1, second_char);
if (memcmp(tmp1, expected, i) || strcmp(tmp1, expected)
|| strncmp(tmp1, expected, i) || strncmp(tmp1, expected, i + 1)
|| strcmp(tmp1, tmp2) >= 0 || memcmp(tmp1, tmp2, i) >= 0
|| strncmp(tmp1, tmp2, i + 1) >= 0 || (int)strlen(tmp1) != i
|| memchr(tmp1, first_char, i) != tmp1 || strchr(tmp1, first_char) != tmp1
|| memchr(tmp1, second_char, i) != tmp1 + z
|| strchr(tmp1, second_char) != tmp1 + z || strcmp(tmp5, tmp6)
|| strncat(tmp7, tmp1, i + 2) != tmp7 || strcmp(tmp7, tmp6)
|| tmp7[2 * i + z] != second_char)
{
eprintf(__LINE__, tmp1, expected, 0);
printf("x is %d\n", x);
printf("i is %d\n", i);
printf("tmp1 is <%p>\n", tmp1);
printf("tmp5 is <%p> <%s>\n", tmp5, tmp5);
printf("tmp6 is <%p> <%s>\n", tmp6, tmp6);
test_failed = 1;
}
for (k = 1; k <= align_test_iterations && k <= i; ++k)
{
if (memcmp(tmp3, tmp4, i - k + 1) != 0 || strncmp(tmp3, tmp4, i - k + 1) != 0)
{
printf("Failure at line %d, comparing %.*s with %.*s\n", __LINE__, i, tmp3,
i, tmp4);
test_failed = 1;
}
tmp4[i - k] = first_char + 1;
if (memcmp(tmp3, tmp4, i) >= 0 || strncmp(tmp3, tmp4, i) >= 0
|| memcmp(tmp4, tmp3, i) <= 0 || strncmp(tmp4, tmp3, i) <= 0)
{
printf("Failure at line %d, comparing %.*s with %.*s\n", __LINE__, i, tmp3,
i, tmp4);
test_failed = 1;
}
tmp4[i - k] = first_char;
}
}
}
j = ((2 * j) >> 2) << 2;
j = ((2 * j) >> 2) << 2;
}
if (test_failed)
abort();
if (test_failed)
abort();
printf("ok\n");
printf("ok\n");
}

View File

@ -1,14 +1,14 @@
/*
Arduino.cpp - Mocks for common Arduino APIs
Copyright © 2016 Ivan Grokhotkov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
*/
@ -41,7 +41,6 @@ extern "C" unsigned long micros()
return ((time.tv_sec - gtod0.tv_sec) * 1000000) + time.tv_usec - gtod0.tv_usec;
}
extern "C" void yield()
{
run_scheduled_recurrent_functions();
@ -58,38 +57,35 @@ extern "C" bool can_yield()
return true;
}
extern "C" void optimistic_yield (uint32_t interval_us)
extern "C" void optimistic_yield(uint32_t interval_us)
{
(void)interval_us;
}
extern "C" void esp_suspend()
{
}
extern "C" void esp_suspend() { }
extern "C" void esp_schedule()
{
}
extern "C" void esp_schedule() { }
extern "C" void esp_yield()
{
}
extern "C" void esp_yield() { }
extern "C" void esp_delay (unsigned long ms)
extern "C" void esp_delay(unsigned long ms)
{
usleep(ms * 1000);
}
bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) {
bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms)
{
uint32_t expired = millis() - start_ms;
if (expired >= timeout_ms) {
if (expired >= timeout_ms)
{
return true;
}
esp_delay(std::min((timeout_ms - expired), intvl_ms));
return false;
}
extern "C" void __panic_func(const char* file, int line, const char* func) {
extern "C" void __panic_func(const char* file, int line, const char* func)
{
(void)file;
(void)line;
(void)func;
@ -107,15 +103,14 @@ extern "C" void delayMicroseconds(unsigned int us)
}
#include "cont.h"
cont_t* g_pcont = NULL;
extern "C" void cont_suspend(cont_t*)
{
}
cont_t* g_pcont = NULL;
extern "C" void cont_suspend(cont_t*) { }
extern "C" int __mockverbose (const char* fmt, ...)
extern "C" int __mockverbose(const char* fmt, ...)
{
(void)fmt;
return 0;
}
int mockverbose (const char* fmt, ...) __attribute__ ((weak, alias("__mockverbose"), format (printf, 1, 2)));
int mockverbose(const char* fmt, ...)
__attribute__((weak, alias("__mockverbose"), format(printf, 1, 2)));

View File

@ -1,14 +1,14 @@
/*
Arduino.cpp - Mocks for common Arduino APIs
Copyright © 2016 Ivan Grokhotkov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
*/
@ -17,4 +17,3 @@
#include <catch.hpp>
#include <sys/time.h>
#include "Arduino.h"

View File

@ -30,7 +30,7 @@
*/
#include <Arduino.h>
#include <user_interface.h> // wifi_get_ip_info()
#include <user_interface.h> // wifi_get_ip_info()
#include <signal.h>
#include <unistd.h>
@ -41,280 +41,280 @@
#define MOCK_PORT_SHIFTER 9000
bool user_exit = false;
bool run_once = false;
const char* host_interface = nullptr;
size_t spiffs_kb = 1024;
size_t littlefs_kb = 1024;
bool ignore_sigint = false;
bool restore_tty = false;
bool mockdebug = false;
int mock_port_shifter = MOCK_PORT_SHIFTER;
const char* fspath = nullptr;
bool user_exit = false;
bool run_once = false;
const char* host_interface = nullptr;
size_t spiffs_kb = 1024;
size_t littlefs_kb = 1024;
bool ignore_sigint = false;
bool restore_tty = false;
bool mockdebug = false;
int mock_port_shifter = MOCK_PORT_SHIFTER;
const char* fspath = nullptr;
#define STDIN STDIN_FILENO
static struct termios initial_settings;
int mockverbose (const char* fmt, ...)
int mockverbose(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (mockdebug)
return fprintf(stderr, MOCK) + vfprintf(stderr, fmt, ap);
return 0;
va_list ap;
va_start(ap, fmt);
if (mockdebug)
return fprintf(stderr, MOCK) + vfprintf(stderr, fmt, ap);
return 0;
}
static int mock_start_uart(void)
{
struct termios settings;
struct termios settings;
if (!isatty(STDIN))
{
perror("setting tty in raw mode: isatty(STDIN)");
return -1;
}
if (tcgetattr(STDIN, &initial_settings) < 0)
{
perror("setting tty in raw mode: tcgetattr(STDIN)");
return -1;
}
settings = initial_settings;
settings.c_lflag &= ~(ignore_sigint ? ISIG : 0);
settings.c_lflag &= ~(ECHO | ICANON);
settings.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IXON);
settings.c_oflag |= (ONLCR);
settings.c_cc[VMIN] = 0;
settings.c_cc[VTIME] = 0;
if (tcsetattr(STDIN, TCSANOW, &settings) < 0)
{
perror("setting tty in raw mode: tcsetattr(STDIN)");
return -1;
}
restore_tty = true;
return 0;
if (!isatty(STDIN))
{
perror("setting tty in raw mode: isatty(STDIN)");
return -1;
}
if (tcgetattr(STDIN, &initial_settings) < 0)
{
perror("setting tty in raw mode: tcgetattr(STDIN)");
return -1;
}
settings = initial_settings;
settings.c_lflag &= ~(ignore_sigint ? ISIG : 0);
settings.c_lflag &= ~(ECHO | ICANON);
settings.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IXON);
settings.c_oflag |= (ONLCR);
settings.c_cc[VMIN] = 0;
settings.c_cc[VTIME] = 0;
if (tcsetattr(STDIN, TCSANOW, &settings) < 0)
{
perror("setting tty in raw mode: tcsetattr(STDIN)");
return -1;
}
restore_tty = true;
return 0;
}
static int mock_stop_uart(void)
{
if (!restore_tty) return 0;
if (!isatty(STDIN)) {
perror("restoring tty: isatty(STDIN)");
return -1;
}
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0)
{
perror("restoring tty: tcsetattr(STDIN)");
return -1;
}
printf("\e[?25h"); // show cursor
return (0);
if (!restore_tty)
return 0;
if (!isatty(STDIN))
{
perror("restoring tty: isatty(STDIN)");
return -1;
}
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0)
{
perror("restoring tty: tcsetattr(STDIN)");
return -1;
}
printf("\e[?25h"); // show cursor
return (0);
}
static uint8_t mock_read_uart(void)
{
uint8_t ch = 0;
return (read(STDIN, &ch, 1) == 1) ? ch : 0;
uint8_t ch = 0;
return (read(STDIN, &ch, 1) == 1) ? ch : 0;
}
void help (const char* argv0, int exitcode)
void help(const char* argv0, int exitcode)
{
printf(
"%s - compiled with esp8266/arduino emulator\n"
"options:\n"
"\t-h\n"
"\tnetwork:\n"
"\t-i <interface> - use this interface for IP address\n"
"\t-l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
"\t-s - port shifter (default: %d, when root: 0)\n"
"\tterminal:\n"
"\t-b - blocking tty/mocked-uart (default: not blocking tty)\n"
"\t-T - show timestamp on output\n"
"\tFS:\n"
"\t-P - path for fs-persistent files (default: %s-)\n"
"\t-S - spiffs size in KBytes (default: %zd)\n"
"\t-L - littlefs size in KBytes (default: %zd)\n"
"\t (spiffs, littlefs: negative value will force mismatched size)\n"
"\tgeneral:\n"
"\t-c - ignore CTRL-C (send it via Serial)\n"
"\t-f - no throttle (possibly 100%%CPU)\n"
"\t-1 - run loop once then exit (for host testing)\n"
"\t-v - verbose\n"
, argv0, MOCK_PORT_SHIFTER, argv0, spiffs_kb, littlefs_kb);
exit(exitcode);
printf("%s - compiled with esp8266/arduino emulator\n"
"options:\n"
"\t-h\n"
"\tnetwork:\n"
"\t-i <interface> - use this interface for IP address\n"
"\t-l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
"\t-s - port shifter (default: %d, when root: 0)\n"
"\tterminal:\n"
"\t-b - blocking tty/mocked-uart (default: not blocking tty)\n"
"\t-T - show timestamp on output\n"
"\tFS:\n"
"\t-P - path for fs-persistent files (default: %s-)\n"
"\t-S - spiffs size in KBytes (default: %zd)\n"
"\t-L - littlefs size in KBytes (default: %zd)\n"
"\t (spiffs, littlefs: negative value will force mismatched size)\n"
"\tgeneral:\n"
"\t-c - ignore CTRL-C (send it via Serial)\n"
"\t-f - no throttle (possibly 100%%CPU)\n"
"\t-1 - run loop once then exit (for host testing)\n"
"\t-v - verbose\n",
argv0, MOCK_PORT_SHIFTER, argv0, spiffs_kb, littlefs_kb);
exit(exitcode);
}
static struct option options[] =
{
{ "help", no_argument, NULL, 'h' },
{ "fast", no_argument, NULL, 'f' },
{ "local", no_argument, NULL, 'l' },
{ "sigint", no_argument, NULL, 'c' },
{ "blockinguart", no_argument, NULL, 'b' },
{ "verbose", no_argument, NULL, 'v' },
{ "timestamp", no_argument, NULL, 'T' },
{ "interface", required_argument, NULL, 'i' },
{ "fspath", required_argument, NULL, 'P' },
{ "spiffskb", required_argument, NULL, 'S' },
{ "littlefskb", required_argument, NULL, 'L' },
{ "portshifter", required_argument, NULL, 's' },
{ "once", no_argument, NULL, '1' },
static struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "fast", no_argument, NULL, 'f' },
{ "local", no_argument, NULL, 'l' },
{ "sigint", no_argument, NULL, 'c' },
{ "blockinguart", no_argument, NULL, 'b' },
{ "verbose", no_argument, NULL, 'v' },
{ "timestamp", no_argument, NULL, 'T' },
{ "interface", required_argument, NULL, 'i' },
{ "fspath", required_argument, NULL, 'P' },
{ "spiffskb", required_argument, NULL, 'S' },
{ "littlefskb", required_argument, NULL, 'L' },
{ "portshifter", required_argument, NULL, 's' },
{ "once", no_argument, NULL, '1' },
};
void cleanup ()
void cleanup()
{
mock_stop_spiffs();
mock_stop_littlefs();
mock_stop_uart();
mock_stop_spiffs();
mock_stop_littlefs();
mock_stop_uart();
}
void make_fs_filename (String& name, const char* fspath, const char* argv0)
void make_fs_filename(String& name, const char* fspath, const char* argv0)
{
name.clear();
if (fspath)
{
int lastSlash = -1;
for (int i = 0; argv0[i]; i++)
if (argv0[i] == '/')
lastSlash = i;
name = fspath;
name += '/';
name += &argv0[lastSlash + 1];
}
else
name = argv0;
name.clear();
if (fspath)
{
int lastSlash = -1;
for (int i = 0; argv0[i]; i++)
if (argv0[i] == '/')
lastSlash = i;
name = fspath;
name += '/';
name += &argv0[lastSlash + 1];
}
else
name = argv0;
}
void control_c (int sig)
void control_c(int sig)
{
(void)sig;
(void)sig;
if (user_exit)
{
fprintf(stderr, MOCK "stuck, killing\n");
cleanup();
exit(1);
}
user_exit = true;
if (user_exit)
{
fprintf(stderr, MOCK "stuck, killing\n");
cleanup();
exit(1);
}
user_exit = true;
}
int main (int argc, char* const argv [])
int main(int argc, char* const argv[])
{
bool fast = false;
blocking_uart = false; // global
bool fast = false;
blocking_uart = false; // global
signal(SIGINT, control_c);
signal(SIGTERM, control_c);
if (geteuid() == 0)
mock_port_shifter = 0;
else
mock_port_shifter = MOCK_PORT_SHIFTER;
signal(SIGINT, control_c);
signal(SIGTERM, control_c);
if (geteuid() == 0)
mock_port_shifter = 0;
else
mock_port_shifter = MOCK_PORT_SHIFTER;
for (;;)
{
int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:P:1", options, NULL);
if (n < 0)
break;
switch (n)
{
case 'h':
help(argv[0], EXIT_SUCCESS);
break;
case 'i':
host_interface = optarg;
break;
case 'l':
global_ipv4_netfmt = NO_GLOBAL_BINDING;
break;
case 's':
mock_port_shifter = atoi(optarg);
break;
case 'c':
ignore_sigint = true;
break;
case 'f':
fast = true;
break;
case 'S':
spiffs_kb = atoi(optarg);
break;
case 'L':
littlefs_kb = atoi(optarg);
break;
case 'P':
fspath = optarg;
break;
case 'b':
blocking_uart = true;
break;
case 'v':
mockdebug = true;
break;
case 'T':
serial_timestamp = true;
break;
case '1':
run_once = true;
break;
default:
help(argv[0], EXIT_FAILURE);
}
}
for (;;)
{
int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:P:1", options, NULL);
if (n < 0)
break;
switch (n)
{
case 'h':
help(argv[0], EXIT_SUCCESS);
break;
case 'i':
host_interface = optarg;
break;
case 'l':
global_ipv4_netfmt = NO_GLOBAL_BINDING;
break;
case 's':
mock_port_shifter = atoi(optarg);
break;
case 'c':
ignore_sigint = true;
break;
case 'f':
fast = true;
break;
case 'S':
spiffs_kb = atoi(optarg);
break;
case 'L':
littlefs_kb = atoi(optarg);
break;
case 'P':
fspath = optarg;
break;
case 'b':
blocking_uart = true;
break;
case 'v':
mockdebug = true;
break;
case 'T':
serial_timestamp = true;
break;
case '1':
run_once = true;
break;
default:
help(argv[0], EXIT_FAILURE);
}
}
mockverbose("server port shifter: %d\n", mock_port_shifter);
mockverbose("server port shifter: %d\n", mock_port_shifter);
if (spiffs_kb)
{
String name;
make_fs_filename(name, fspath, argv[0]);
name += "-spiffs";
name += String(spiffs_kb > 0? spiffs_kb: -spiffs_kb, DEC);
name += "KB";
mock_start_spiffs(name, spiffs_kb);
}
if (spiffs_kb)
{
String name;
make_fs_filename(name, fspath, argv[0]);
name += "-spiffs";
name += String(spiffs_kb > 0 ? spiffs_kb : -spiffs_kb, DEC);
name += "KB";
mock_start_spiffs(name, spiffs_kb);
}
if (littlefs_kb)
{
String name;
make_fs_filename(name, fspath, argv[0]);
name += "-littlefs";
name += String(littlefs_kb > 0? littlefs_kb: -littlefs_kb, DEC);
name += "KB";
mock_start_littlefs(name, littlefs_kb);
}
if (littlefs_kb)
{
String name;
make_fs_filename(name, fspath, argv[0]);
name += "-littlefs";
name += String(littlefs_kb > 0 ? littlefs_kb : -littlefs_kb, DEC);
name += "KB";
mock_start_littlefs(name, littlefs_kb);
}
// setup global global_ipv4_netfmt
wifi_get_ip_info(0, nullptr);
// setup global global_ipv4_netfmt
wifi_get_ip_info(0, nullptr);
if (!blocking_uart)
{
// set stdin to non blocking mode
mock_start_uart();
}
if (!blocking_uart)
{
// set stdin to non blocking mode
mock_start_uart();
}
// install exit handler in case Esp.restart() is called
atexit(cleanup);
// install exit handler in case Esp.restart() is called
atexit(cleanup);
// first call to millis(): now is millis() and micros() beginning
millis();
// first call to millis(): now is millis() and micros() beginning
millis();
setup();
while (!user_exit)
{
uint8_t data = mock_read_uart();
setup();
while (!user_exit)
{
uint8_t data = mock_read_uart();
if (data)
uart_new_data(UART0, data);
if (!fast)
usleep(1000); // not 100% cpu, ~1000 loops per second
loop();
loop_end();
check_incoming_udp();
if (data)
uart_new_data(UART0, data);
if (!fast)
usleep(1000); // not 100% cpu, ~1000 loops per second
loop();
loop_end();
check_incoming_udp();
if (run_once)
user_exit = true;
}
cleanup();
if (run_once)
user_exit = true;
}
cleanup();
return 0;
return 0;
}

View File

@ -3,15 +3,14 @@
LittleFSMock* littlefs_mock = nullptr;
void mock_start_littlefs (const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
void mock_start_littlefs(const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
{
littlefs_mock = new LittleFSMock(size_kb * 1024, block_kb * 1024, page_b, fname);
littlefs_mock = new LittleFSMock(size_kb * 1024, block_kb * 1024, page_b, fname);
}
void mock_stop_littlefs ()
void mock_stop_littlefs()
{
if (littlefs_mock)
delete littlefs_mock;
littlefs_mock = nullptr;
if (littlefs_mock)
delete littlefs_mock;
littlefs_mock = nullptr;
}

View File

@ -3,15 +3,14 @@
SpiffsMock* spiffs_mock = nullptr;
void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
void mock_start_spiffs(const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
{
spiffs_mock = new SpiffsMock(size_kb * 1024, block_kb * 1024, page_b, fname);
spiffs_mock = new SpiffsMock(size_kb * 1024, block_kb * 1024, page_b, fname);
}
void mock_stop_spiffs ()
void mock_stop_spiffs()
{
if (spiffs_mock)
delete spiffs_mock;
spiffs_mock = nullptr;
if (spiffs_mock)
delete spiffs_mock;
spiffs_mock = nullptr;
}

View File

@ -33,28 +33,28 @@
#include <poll.h>
#include <map>
std::map<int,UdpContext*> udps;
std::map<int, UdpContext*> udps;
void register_udp (int sock, UdpContext* udp)
void register_udp(int sock, UdpContext* udp)
{
if (udp)
udps[sock] = udp;
else
udps.erase(sock);
if (udp)
udps[sock] = udp;
else
udps.erase(sock);
}
void check_incoming_udp ()
void check_incoming_udp()
{
// check incoming udp
for (auto& udp: udps)
{
pollfd p;
p.fd = udp.first;
p.events = POLLIN;
if (poll(&p, 1, 0) && p.revents == POLLIN)
{
mockverbose("UDP poll(%d) -> cb\r", p.fd);
udp.second->mock_cb();
}
}
// check incoming udp
for (auto& udp : udps)
{
pollfd p;
p.fd = udp.first;
p.events = POLLIN;
if (poll(&p, 1, 0) && p.revents == POLLIN)
{
mockverbose("UDP poll(%d) -> cb\r", p.fd);
udp.second->mock_cb();
}
}
}

View File

@ -39,168 +39,173 @@
#include <fcntl.h>
#include <errno.h>
int mockSockSetup (int sock)
int mockSockSetup(int sock)
{
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
{
perror("socket fcntl(O_NONBLOCK)");
close(sock);
return -1;
}
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
{
perror("socket fcntl(O_NONBLOCK)");
close(sock);
return -1;
}
#ifndef MSG_NOSIGNAL
int i = 1;
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i) == -1)
{
perror("sockopt(SO_NOSIGPIPE)(macOS)");
close(sock);
return -1;
}
int i = 1;
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i) == -1)
{
perror("sockopt(SO_NOSIGPIPE)(macOS)");
close(sock);
return -1;
}
#endif
return sock;
return sock;
}
int mockConnect (uint32_t ipv4, int& sock, int port)
int mockConnect(uint32_t ipv4, int& sock, int port)
{
struct sockaddr_in server;
if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror(MOCK "ClientContext:connect: ::socket()");
return 0;
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
memcpy(&server.sin_addr, &ipv4, 4);
if (::connect(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
{
perror(MOCK "ClientContext::connect: ::connect()");
return 0;
}
struct sockaddr_in server;
if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror(MOCK "ClientContext:connect: ::socket()");
return 0;
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
memcpy(&server.sin_addr, &ipv4, 4);
if (::connect(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
{
perror(MOCK "ClientContext::connect: ::connect()");
return 0;
}
return mockSockSetup(sock) == -1? 0: 1;
return mockSockSetup(sock) == -1 ? 0 : 1;
}
ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
ssize_t mockFillInBuf(int sock, char* ccinbuf, size_t& ccinbufsize)
{
size_t maxread = CCBUFSIZE - ccinbufsize;
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);
size_t maxread = CCBUFSIZE - ccinbufsize;
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);
if (ret == 0)
{
// connection closed
// nothing is read
return 0;
}
if (ret == 0)
{
// connection closed
// nothing is read
return 0;
}
if (ret == -1)
{
if (errno != EAGAIN)
{
fprintf(stderr, MOCK "ClientContext::(read/peek fd=%i): filling buffer for %zd bytes: %s\n", sock, maxread, strerror(errno));
if (ret == -1)
{
if (errno != EAGAIN)
{
fprintf(stderr,
MOCK "ClientContext::(read/peek fd=%i): filling buffer for %zd bytes: %s\n",
sock, maxread, strerror(errno));
// error
return -1;
}
ret = 0;
}
return -1;
}
ret = 0;
}
ccinbufsize += ret;
return ret;
ccinbufsize += ret;
return ret;
}
ssize_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
ssize_t mockPeekBytes(int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf,
size_t& ccinbufsize)
{
// usersize==0: peekAvailable()
if (usersize > CCBUFSIZE)
mockverbose("CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
if (usersize > CCBUFSIZE)
mockverbose("CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE,
usersize - CCBUFSIZE, usersize);
struct pollfd p;
size_t retsize = 0;
do
{
if (usersize && usersize <= ccinbufsize)
{
// data already buffered
retsize = usersize;
break;
}
// check incoming data data
if (mockFillInBuf(sock, ccinbuf, ccinbufsize) < 0)
{
return -1;
}
struct pollfd p;
size_t retsize = 0;
do
{
if (usersize && usersize <= ccinbufsize)
{
// data already buffered
retsize = usersize;
break;
}
// check incoming data data
if (mockFillInBuf(sock, ccinbuf, ccinbufsize) < 0)
{
return -1;
}
if (usersize == 0 && ccinbufsize)
// peekAvailable
return ccinbufsize;
if (usersize <= ccinbufsize)
{
// data just received
retsize = usersize;
break;
}
// wait for more data until timeout
p.fd = sock;
p.events = POLLIN;
} while (poll(&p, 1, timeout_ms) == 1);
if (usersize <= ccinbufsize)
{
// data just received
retsize = usersize;
break;
}
// wait for more data until timeout
p.fd = sock;
p.events = POLLIN;
} while (poll(&p, 1, timeout_ms) == 1);
if (dst)
{
memcpy(dst, ccinbuf, retsize);
}
return retsize;
return retsize;
}
ssize_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
ssize_t mockRead(int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf,
size_t& ccinbufsize)
{
ssize_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
if (copied < 0)
return -1;
// swallow (XXX use a circular buffer)
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
ccinbufsize -= copied;
return copied;
ssize_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
if (copied < 0)
return -1;
// swallow (XXX use a circular buffer)
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
ccinbufsize -= copied;
return copied;
}
ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
{
size_t sent = 0;
while (sent < size)
{
struct pollfd p;
p.fd = sock;
p.events = POLLOUT;
int ret = poll(&p, 1, timeout_ms);
if (ret == -1)
{
fprintf(stderr, MOCK "ClientContext::write(%d): %s\n", sock, strerror(errno));
return -1;
}
if (ret)
{
ssize_t mockWrite(int sock, const uint8_t* data, size_t size, int timeout_ms)
{
size_t sent = 0;
while (sent < size)
{
struct pollfd p;
p.fd = sock;
p.events = POLLOUT;
int ret = poll(&p, 1, timeout_ms);
if (ret == -1)
{
fprintf(stderr, MOCK "ClientContext::write(%d): %s\n", sock, strerror(errno));
return -1;
}
if (ret)
{
#ifndef MSG_NOSIGNAL
ret = ::write(sock, data + sent, size - sent);
ret = ::write(sock, data + sent, size - sent);
#else
ret = ::send(sock, data + sent, size - sent, MSG_NOSIGNAL);
ret = ::send(sock, data + sent, size - sent, MSG_NOSIGNAL);
#endif
if (ret == -1)
{
fprintf(stderr, MOCK "ClientContext::write/send(%d): %s\n", sock, strerror(errno));
return -1;
}
sent += ret;
if (sent < size)
fprintf(stderr, MOCK "ClientContext::write: sent %d bytes (%zd / %zd)\n", ret, sent, size);
}
}
if (ret == -1)
{
fprintf(stderr, MOCK "ClientContext::write/send(%d): %s\n", sock, strerror(errno));
return -1;
}
sent += ret;
if (sent < size)
fprintf(stderr, MOCK "ClientContext::write: sent %d bytes (%zd / %zd)\n", ret, sent,
size);
}
}
#ifdef DEBUG_ESP_WIFI
mockverbose(MOCK "ClientContext::write: total sent %zd bytes\n", sent);
#endif
return sent;
return sent;
}

View File

@ -35,23 +35,24 @@
#include <WiFiClient.h>
#include <include/ClientContext.h>
#include <netdb.h> // gethostbyname
#include <netdb.h> // gethostbyname
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg)
err_t dns_gethostbyname(const char* hostname, ip_addr_t* addr, dns_found_callback found,
void* callback_arg)
{
(void)callback_arg;
(void)found;
struct hostent* hbn = gethostbyname(hostname);
if (!hbn)
return ERR_TIMEOUT;
addr->addr = *(uint32_t*)hbn->h_addr_list[0];
return ERR_OK;
(void)callback_arg;
(void)found;
struct hostent* hbn = gethostbyname(hostname);
if (!hbn)
return ERR_TIMEOUT;
addr->addr = *(uint32_t*)hbn->h_addr_list[0];
return ERR_OK;
}
static struct tcp_pcb mock_tcp_pcb;
tcp_pcb* tcp_new (void)
tcp_pcb* tcp_new(void)
{
// this is useless
// ClientContext is setting the source port and we don't care here
return &mock_tcp_pcb;
// this is useless
// ClientContext is setting the source port and we don't care here
return &mock_tcp_pcb;
}

View File

@ -32,46 +32,53 @@
#ifndef EEPROM_MOCK
#define EEPROM_MOCK
class EEPROMClass {
class EEPROMClass
{
public:
EEPROMClass(uint32_t sector);
EEPROMClass(void);
~EEPROMClass();
EEPROMClass(uint32_t sector);
EEPROMClass(void);
~EEPROMClass();
void begin(size_t size);
uint8_t read(int address);
void write(int address, uint8_t val);
bool commit();
void end();
void begin(size_t size);
uint8_t read(int address);
void write(int address, uint8_t val);
bool commit();
void end();
template<typename T>
T& get(int const address, T& t)
{
if (address < 0 || address + sizeof(T) > _size)
return t;
for (size_t i = 0; i < sizeof(T); i++)
((uint8_t*)&t)[i] = read(i);
return t;
}
template<typename T>
T& get(int const address, T& t)
{
if (address < 0 || address + sizeof(T) > _size)
return t;
for (size_t i = 0; i < sizeof(T); i++)
((uint8_t*)&t)[i] = read(i);
return t;
}
template<typename T>
const T& put(int const address, const T& t)
{
if (address < 0 || address + sizeof(T) > _size)
return t;
for (size_t i = 0; i < sizeof(T); i++)
write(i, ((uint8_t*)&t)[i]);
return t;
}
template<typename T>
const T& put(int const address, const T& t)
{
if (address < 0 || address + sizeof(T) > _size)
return t;
for (size_t i = 0; i < sizeof(T); i++)
write(i, ((uint8_t*)&t)[i]);
return t;
}
size_t length() { return _size; }
size_t length()
{
return _size;
}
//uint8_t& operator[](int const address) { return read(address); }
uint8_t operator[] (int address) { return read(address); }
// uint8_t& operator[](int const address) { return read(address); }
uint8_t operator[](int address)
{
return read(address);
}
protected:
size_t _size = 0;
int _fd = -1;
size_t _size = 0;
int _fd = -1;
};
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)

View File

@ -42,60 +42,82 @@
static uint8_t _mode[GPIONUM];
static uint8_t _gpio[GPIONUM];
void pinMode (uint8_t pin, uint8_t mode)
void pinMode(uint8_t pin, uint8_t mode)
{
#define xxx(mode) case mode: m=STRHELPER(mode); break
const char* m;
switch (mode)
{
case INPUT: m="INPUT"; break;
case OUTPUT: m="OUTPUT"; break;
case INPUT_PULLUP: m="INPUT_PULLUP"; break;
case OUTPUT_OPEN_DRAIN: m="OUTPUT_OPEN_DRAIN"; break;
case INPUT_PULLDOWN_16: m="INPUT_PULLDOWN_16"; break;
case WAKEUP_PULLUP: m="WAKEUP_PULLUP"; break;
case WAKEUP_PULLDOWN: m="WAKEUP_PULLDOWN"; break;
default: m="(special)";
}
VERBOSE("gpio%d: mode='%s'\n", pin, m);
#define xxx(mode) \
case mode: \
m = STRHELPER(mode); \
break
const char* m;
switch (mode)
{
case INPUT:
m = "INPUT";
break;
case OUTPUT:
m = "OUTPUT";
break;
case INPUT_PULLUP:
m = "INPUT_PULLUP";
break;
case OUTPUT_OPEN_DRAIN:
m = "OUTPUT_OPEN_DRAIN";
break;
case INPUT_PULLDOWN_16:
m = "INPUT_PULLDOWN_16";
break;
case WAKEUP_PULLUP:
m = "WAKEUP_PULLUP";
break;
case WAKEUP_PULLDOWN:
m = "WAKEUP_PULLDOWN";
break;
default:
m = "(special)";
}
VERBOSE("gpio%d: mode='%s'\n", pin, m);
if (pin < GPIONUM)
{
_mode[pin] = mode;
_mode[pin] = mode;
}
}
void digitalWrite(uint8_t pin, uint8_t val)
{
VERBOSE("digitalWrite(pin=%d val=%d)\n", pin, val);
if (pin < GPIONUM) {
VERBOSE("digitalWrite(pin=%d val=%d)\n", pin, val);
if (pin < GPIONUM)
{
_gpio[pin] = val;
}
}
void analogWrite(uint8_t pin, int val)
{
VERBOSE("analogWrite(pin=%d, val=%d\n", pin, val);
VERBOSE("analogWrite(pin=%d, val=%d\n", pin, val);
}
int analogRead(uint8_t pin)
{
(void)pin;
return 512;
(void)pin;
return 512;
}
void analogWriteRange(uint32_t range)
{
VERBOSE("analogWriteRange(range=%d)\n", range);
VERBOSE("analogWriteRange(range=%d)\n", range);
}
int digitalRead(uint8_t pin)
{
VERBOSE("digitalRead(%d)\n", pin);
VERBOSE("digitalRead(%d)\n", pin);
if (pin < GPIONUM) {
return _gpio[pin] != 0;
} else {
return 0;
if (pin < GPIONUM)
{
return _gpio[pin] != 0;
}
else
{
return 0;
}
}

View File

@ -42,52 +42,52 @@
#define EEPROM_FILE_NAME "eeprom"
EEPROMClass::EEPROMClass ()
{
}
EEPROMClass::EEPROMClass() { }
EEPROMClass::~EEPROMClass ()
EEPROMClass::~EEPROMClass()
{
if (_fd >= 0)
close(_fd);
if (_fd >= 0)
close(_fd);
}
void EEPROMClass::begin(size_t size)
{
_size = size;
if ( (_fd = open(EEPROM_FILE_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1
|| ftruncate(_fd, size) == -1)
{
fprintf(stderr, MOCK "EEPROM: cannot open/create '%s' for r/w: %s\n\r", EEPROM_FILE_NAME, strerror(errno));
_fd = -1;
}
_size = size;
if ((_fd = open(EEPROM_FILE_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))
== -1
|| ftruncate(_fd, size) == -1)
{
fprintf(stderr, MOCK "EEPROM: cannot open/create '%s' for r/w: %s\n\r", EEPROM_FILE_NAME,
strerror(errno));
_fd = -1;
}
}
void EEPROMClass::end()
{
if (_fd != -1)
close(_fd);
if (_fd != -1)
close(_fd);
}
bool EEPROMClass::commit()
{
return true;
return true;
}
uint8_t EEPROMClass::read (int x)
uint8_t EEPROMClass::read(int x)
{
char c = 0;
if (pread(_fd, &c, 1, x) != 1)
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
return c;
char c = 0;
if (pread(_fd, &c, 1, x) != 1)
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
return c;
}
void EEPROMClass::write (int x, uint8_t c)
void EEPROMClass::write(int x, uint8_t c)
{
if (x > (int)_size)
fprintf(stderr, MOCK "### eeprom beyond\r\n");
else if (pwrite(_fd, &c, 1, x) != 1)
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
if (x > (int)_size)
fprintf(stderr, MOCK "### eeprom beyond\r\n");
else if (pwrite(_fd, &c, 1, x) != 1)
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
}
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)

View File

@ -36,204 +36,223 @@
#include <stdlib.h>
unsigned long long operator"" _kHz(unsigned long long x) {
unsigned long long operator"" _kHz(unsigned long long x)
{
return x * 1000;
}
unsigned long long operator"" _MHz(unsigned long long x) {
unsigned long long operator"" _MHz(unsigned long long x)
{
return x * 1000 * 1000;
}
unsigned long long operator"" _GHz(unsigned long long x) {
unsigned long long operator"" _GHz(unsigned long long x)
{
return x * 1000 * 1000 * 1000;
}
unsigned long long operator"" _kBit(unsigned long long x) {
unsigned long long operator"" _kBit(unsigned long long x)
{
return x * 1024;
}
unsigned long long operator"" _MBit(unsigned long long x) {
unsigned long long operator"" _MBit(unsigned long long x)
{
return x * 1024 * 1024;
}
unsigned long long operator"" _GBit(unsigned long long x) {
unsigned long long operator"" _GBit(unsigned long long x)
{
return x * 1024 * 1024 * 1024;
}
unsigned long long operator"" _kB(unsigned long long x) {
unsigned long long operator"" _kB(unsigned long long x)
{
return x * 1024;
}
unsigned long long operator"" _MB(unsigned long long x) {
unsigned long long operator"" _MB(unsigned long long x)
{
return x * 1024 * 1024;
}
unsigned long long operator"" _GB(unsigned long long x) {
unsigned long long operator"" _GB(unsigned long long x)
{
return x * 1024 * 1024 * 1024;
}
uint32_t _SPIFFS_start;
void eboot_command_write (struct eboot_command* cmd)
void eboot_command_write(struct eboot_command* cmd)
{
(void)cmd;
(void)cmd;
}
EspClass ESP;
void EspClass::restart ()
void EspClass::restart()
{
mockverbose("Esp.restart(): exiting\n");
exit(EXIT_SUCCESS);
mockverbose("Esp.restart(): exiting\n");
exit(EXIT_SUCCESS);
}
uint32_t EspClass::getChipId()
{
return 0xee1337;
return 0xee1337;
}
bool EspClass::checkFlashConfig(bool needsEquals)
{
(void) needsEquals;
return true;
(void)needsEquals;
return true;
}
uint32_t EspClass::getSketchSize()
{
return 400000;
return 400000;
}
uint32_t EspClass::getFreeHeap()
{
return 30000;
return 30000;
}
uint32_t EspClass::getMaxFreeBlockSize()
{
return 20000;
return 20000;
}
String EspClass::getResetReason()
{
return "Power on";
return "Power on";
}
uint32_t EspClass::getFreeSketchSpace()
{
return 4 * 1024 * 1024;
return 4 * 1024 * 1024;
}
const char *EspClass::getSdkVersion()
const char* EspClass::getSdkVersion()
{
return "2.5.0";
return "2.5.0";
}
uint32_t EspClass::getFlashChipSpeed()
{
return 40;
return 40;
}
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag) {
uint32_t hf = 10 * 1024;
float hm = 1 * 1024;
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
{
uint32_t hf = 10 * 1024;
float hm = 1 * 1024;
if (hfree) *hfree = hf;
if (hmax) *hmax = hm;
if (hfrag) *hfrag = 100 - (sqrt(hm) * 100) / hf;
if (hfree)
*hfree = hf;
if (hmax)
*hmax = hm;
if (hfrag)
*hfrag = 100 - (sqrt(hm) * 100) / hf;
}
void EspClass::getHeapStats(uint32_t* hfree, uint32_t* hmax, uint8_t* hfrag) {
uint32_t hf = 10 * 1024;
float hm = 1 * 1024;
void EspClass::getHeapStats(uint32_t* hfree, uint32_t* hmax, uint8_t* hfrag)
{
uint32_t hf = 10 * 1024;
float hm = 1 * 1024;
if (hfree) *hfree = hf;
if (hmax) *hmax = hm;
if (hfrag) *hfrag = 100 - (sqrt(hm) * 100) / hf;
if (hfree)
*hfree = hf;
if (hmax)
*hmax = hm;
if (hfrag)
*hfrag = 100 - (sqrt(hm) * 100) / hf;
}
bool EspClass::flashEraseSector(uint32_t sector)
{
(void) sector;
return true;
(void)sector;
return true;
}
FlashMode_t EspClass::getFlashChipMode()
{
return FM_DOUT;
return FM_DOUT;
}
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
{
(void) byte;
return FM_DOUT;
(void)byte;
return FM_DOUT;
}
bool EspClass::flashWrite(uint32_t offset, const uint32_t *data, size_t size)
bool EspClass::flashWrite(uint32_t offset, const uint32_t* data, size_t size)
{
(void)offset;
(void)data;
(void)size;
return true;
(void)offset;
(void)data;
(void)size;
return true;
}
bool EspClass::flashWrite(uint32_t offset, const uint8_t *data, size_t size)
bool EspClass::flashWrite(uint32_t offset, const uint8_t* data, size_t size)
{
(void)offset;
(void)data;
(void)size;
return true;
(void)offset;
(void)data;
(void)size;
return true;
}
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
bool EspClass::flashRead(uint32_t offset, uint32_t* data, size_t size)
{
(void)offset;
(void)data;
(void)size;
return true;
(void)offset;
(void)data;
(void)size;
return true;
}
bool EspClass::flashRead(uint32_t offset, uint8_t *data, size_t size)
bool EspClass::flashRead(uint32_t offset, uint8_t* data, size_t size)
{
(void)offset;
(void)data;
(void)size;
return true;
(void)offset;
(void)data;
(void)size;
return true;
}
uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
switch(byte & 0x0F) {
case 0x0: // 4 Mbit (512KB)
return (512_kB);
case 0x1: // 2 MBit (256KB)
return (256_kB);
case 0x2: // 8 MBit (1MB)
return (1_MB);
case 0x3: // 16 MBit (2MB)
return (2_MB);
case 0x4: // 32 MBit (4MB)
return (4_MB);
case 0x8: // 64 MBit (8MB)
return (8_MB);
case 0x9: // 128 MBit (16MB)
return (16_MB);
default: // fail?
return 0;
uint32_t EspClass::magicFlashChipSize(uint8_t byte)
{
switch (byte & 0x0F)
{
case 0x0: // 4 Mbit (512KB)
return (512_kB);
case 0x1: // 2 MBit (256KB)
return (256_kB);
case 0x2: // 8 MBit (1MB)
return (1_MB);
case 0x3: // 16 MBit (2MB)
return (2_MB);
case 0x4: // 32 MBit (4MB)
return (4_MB);
case 0x8: // 64 MBit (8MB)
return (8_MB);
case 0x9: // 128 MBit (16MB)
return (16_MB);
default: // fail?
return 0;
}
}
uint32_t EspClass::getFlashChipRealSize(void)
{
return magicFlashChipSize(4);
return magicFlashChipSize(4);
}
uint32_t EspClass::getFlashChipSize(void)
{
return magicFlashChipSize(4);
return magicFlashChipSize(4);
}
String EspClass::getFullVersion ()
String EspClass::getFullVersion()
{
return "emulation-on-host";
return "emulation-on-host";
}
uint32_t EspClass::getFreeContStack()
@ -241,9 +260,7 @@ uint32_t EspClass::getFreeContStack()
return 4000;
}
void EspClass::resetFreeContStack()
{
}
void EspClass::resetFreeContStack() { }
uint32_t EspClass::getCycleCount()
{
@ -257,23 +274,15 @@ uint32_t esp_get_cycle_count()
return (((uint64_t)t.tv_sec) * 1000000 + t.tv_usec) * (F_CPU / 1000000);
}
void EspClass::setDramHeap()
{
}
void EspClass::setDramHeap() { }
void EspClass::setIramHeap()
{
}
void EspClass::setIramHeap() { }
void EspClass::setExternalHeap()
{
}
void EspClass::setExternalHeap() { }
void EspClass::resetHeap()
{
}
void EspClass::resetHeap() { }
void EspClass::reset ()
void EspClass::reset()
{
abort();
}

View File

@ -35,29 +35,23 @@
SPIClass SPI;
#endif
SPIClass::SPIClass ()
{
}
SPIClass::SPIClass() { }
uint8_t SPIClass::transfer(uint8_t data)
{
return data;
return data;
}
void SPIClass::begin()
{
}
void SPIClass::begin() { }
void SPIClass::end()
{
}
void SPIClass::end() { }
void SPIClass::setFrequency(uint32_t freq)
{
(void)freq;
(void)freq;
}
void SPIClass::setHwCs(bool use)
{
(void)use;
(void)use;
}

View File

@ -34,56 +34,91 @@
extern "C"
{
uint32_t lwip_htonl(uint32_t hostlong)
{
return htonl(hostlong);
}
uint16_t lwip_htons(uint16_t hostshort)
{
return htons(hostshort);
}
uint32_t lwip_ntohl(uint32_t netlong)
{
return ntohl(netlong);
}
uint16_t lwip_ntohs(uint16_t netshort)
{
return ntohs(netshort);
}
uint32_t lwip_htonl (uint32_t hostlong) { return htonl(hostlong); }
uint16_t lwip_htons (uint16_t hostshort) { return htons(hostshort); }
uint32_t lwip_ntohl (uint32_t netlong) { return ntohl(netlong); }
uint16_t lwip_ntohs (uint16_t netshort) { return ntohs(netshort); }
char* ets_strcpy(char* d, const char* s)
{
return strcpy(d, s);
}
char* ets_strncpy(char* d, const char* s, size_t n)
{
return strncpy(d, s, n);
}
size_t ets_strlen(const char* s)
{
return strlen(s);
}
char* ets_strcpy (char* d, const char* s) { return strcpy(d, s); }
char* ets_strncpy (char* d, const char* s, size_t n) { return strncpy(d, s, n); }
size_t ets_strlen (const char* s) { return strlen(s); }
int ets_printf (const char* fmt, ...)
{
int ets_printf(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int len = vprintf(fmt, ap);
va_end(ap);
return len;
}
int len = vprintf(fmt, ap);
va_end(ap);
return len;
}
void stack_thunk_add_ref() { }
void stack_thunk_del_ref() { }
void stack_thunk_repaint() { }
void stack_thunk_add_ref() { }
void stack_thunk_del_ref() { }
void stack_thunk_repaint() { }
uint32_t stack_thunk_get_refcnt() { return 0; }
uint32_t stack_thunk_get_stack_top() { return 0; }
uint32_t stack_thunk_get_stack_bot() { return 0; }
uint32_t stack_thunk_get_cont_sp() { return 0; }
uint32_t stack_thunk_get_max_usage() { return 0; }
void stack_thunk_dump_stack() { }
uint32_t stack_thunk_get_refcnt()
{
return 0;
}
uint32_t stack_thunk_get_stack_top()
{
return 0;
}
uint32_t stack_thunk_get_stack_bot()
{
return 0;
}
uint32_t stack_thunk_get_cont_sp()
{
return 0;
}
uint32_t stack_thunk_get_max_usage()
{
return 0;
}
void stack_thunk_dump_stack() { }
// Thunking macro
#define make_stack_thunk(fcnToThunk)
};
void configTime(int timezone, int daylightOffset_sec,
const char* server1, const char* server2, const char* server3)
void configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2,
const char* server3)
{
(void)server1;
(void)server2;
(void)server3;
(void)server1;
(void)server2;
(void)server3;
mockverbose("configTime: TODO (tz=%dH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec);
mockverbose("configTime: TODO (tz=%dH offset=%dS) (time will be host's)\n", timezone,
daylightOffset_sec);
}
void configTime(const char* tz, const char* server1, const char* server2, const char* server3)
{
(void)server1;
(void)server2;
(void)server3;
(void)server1;
(void)server2;
(void)server3;
mockverbose("configTime: TODO (tz='%s') (time will be host's)\n", tz);
mockverbose("configTime: TODO (tz='%s') (time will be host's)\n", tz);
}

View File

@ -28,475 +28,455 @@
is responsible for feeding the RX FIFO new data by calling uart_new_data().
*/
#include <unistd.h> // write
#include <sys/time.h> // gettimeofday
#include <time.h> // localtime
#include <unistd.h> // write
#include <sys/time.h> // gettimeofday
#include <time.h> // localtime
#include "Arduino.h"
#include "uart.h"
//#define UART_DISCARD_NEWEST
extern "C" {
bool blocking_uart = true; // system default
static int s_uart_debug_nr = UART1;
static uart_t *UART[2] = { NULL, NULL };
struct uart_rx_buffer_
extern "C"
{
size_t size;
size_t rpos;
size_t wpos;
uint8_t * buffer;
};
bool blocking_uart = true; // system default
struct uart_
{
int uart_nr;
int baud_rate;
bool rx_enabled;
bool tx_enabled;
bool rx_overrun;
struct uart_rx_buffer_ * rx_buffer;
};
static int s_uart_debug_nr = UART1;
bool serial_timestamp = false;
static uart_t* UART[2] = { NULL, NULL };
// write one byte to the emulated UART
static void
uart_do_write_char(const int uart_nr, char c)
{
static bool w = false;
struct uart_rx_buffer_
{
size_t size;
size_t rpos;
size_t wpos;
uint8_t* buffer;
};
if (uart_nr >= UART0 && uart_nr <= UART1)
{
if (serial_timestamp && (c == '\n' || c == '\r'))
{
if (w)
{
FILE* out = uart_nr == UART0? stdout: stderr;
timeval tv;
gettimeofday(&tv, nullptr);
const tm* tm = localtime(&tv.tv_sec);
fprintf(out, "\r\n%d:%02d:%02d.%06d: ", tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec);
fflush(out);
w = false;
}
}
else
{
struct uart_
{
int uart_nr;
int baud_rate;
bool rx_enabled;
bool tx_enabled;
bool rx_overrun;
struct uart_rx_buffer_* rx_buffer;
};
bool serial_timestamp = false;
// write one byte to the emulated UART
static void uart_do_write_char(const int uart_nr, char c)
{
static bool w = false;
if (uart_nr >= UART0 && uart_nr <= UART1)
{
if (serial_timestamp && (c == '\n' || c == '\r'))
{
if (w)
{
FILE* out = uart_nr == UART0 ? stdout : stderr;
timeval tv;
gettimeofday(&tv, nullptr);
const tm* tm = localtime(&tv.tv_sec);
fprintf(out, "\r\n%d:%02d:%02d.%06d: ", tm->tm_hour, tm->tm_min, tm->tm_sec,
(int)tv.tv_usec);
fflush(out);
w = false;
}
}
else
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(uart_nr + 1, &c, 1);
write(uart_nr + 1, &c, 1);
#pragma GCC diagnostic pop
w = true;
}
}
}
// write a new byte into the RX FIFO buffer
static void
uart_handle_data(uart_t* uart, uint8_t data)
{
struct uart_rx_buffer_ *rx_buffer = uart->rx_buffer;
size_t nextPos = (rx_buffer->wpos + 1) % rx_buffer->size;
if(nextPos == rx_buffer->rpos)
{
uart->rx_overrun = true;
#ifdef UART_DISCARD_NEWEST
return;
#else
if (++rx_buffer->rpos == rx_buffer->size)
rx_buffer->rpos = 0;
#endif
}
rx_buffer->buffer[rx_buffer->wpos] = data;
rx_buffer->wpos = nextPos;
}
// insert a new byte into the RX FIFO nuffer
void
uart_new_data(const int uart_nr, uint8_t data)
{
uart_t* uart = UART[uart_nr];
if(uart == NULL || !uart->rx_enabled) {
return;
}
uart_handle_data(uart, data);
}
static size_t
uart_rx_available_unsafe(const struct uart_rx_buffer_ * rx_buffer)
{
size_t ret = rx_buffer->wpos - rx_buffer->rpos;
if(rx_buffer->wpos < rx_buffer->rpos)
ret = (rx_buffer->wpos + rx_buffer->size) - rx_buffer->rpos;
return ret;
}
// taking data straight from fifo, only needed in uart_resize_rx_buffer()
static int
uart_read_char_unsafe(uart_t* uart)
{
if (uart_rx_available_unsafe(uart->rx_buffer))
{
// take oldest sw data
int ret = uart->rx_buffer->buffer[uart->rx_buffer->rpos];
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + 1) % uart->rx_buffer->size;
return ret;
}
// unavailable
return -1;
}
/**********************************************************/
/************ UART API FUNCTIONS **************************/
/**********************************************************/
size_t
uart_rx_available(uart_t* uart)
{
if(uart == NULL || !uart->rx_enabled)
return 0;
return uart_rx_available_unsafe(uart->rx_buffer);
}
int
uart_peek_char(uart_t* uart)
{
if(uart == NULL || !uart->rx_enabled)
return -1;
if (!uart_rx_available_unsafe(uart->rx_buffer))
return -1;
return uart->rx_buffer->buffer[uart->rx_buffer->rpos];
}
int
uart_read_char(uart_t* uart)
{
uint8_t ret;
return uart_read(uart, (char*)&ret, 1) ? ret : -1;
}
size_t
uart_read(uart_t* uart, char* userbuffer, size_t usersize)
{
if(uart == NULL || !uart->rx_enabled)
return 0;
if (!blocking_uart)
{
char c;
if (read(0, &c, 1) == 1)
uart_new_data(0, c);
w = true;
}
}
}
size_t ret = 0;
while (ret < usersize && uart_rx_available_unsafe(uart->rx_buffer))
{
// pour sw buffer to user's buffer
// get largest linear length from sw buffer
size_t chunk = uart->rx_buffer->rpos < uart->rx_buffer->wpos ?
uart->rx_buffer->wpos - uart->rx_buffer->rpos :
uart->rx_buffer->size - uart->rx_buffer->rpos;
if (ret + chunk > usersize)
chunk = usersize - ret;
memcpy(userbuffer + ret, uart->rx_buffer->buffer + uart->rx_buffer->rpos, chunk);
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + chunk) % uart->rx_buffer->size;
ret += chunk;
}
return ret;
}
// write a new byte into the RX FIFO buffer
static void uart_handle_data(uart_t* uart, uint8_t data)
{
struct uart_rx_buffer_* rx_buffer = uart->rx_buffer;
size_t
uart_resize_rx_buffer(uart_t* uart, size_t new_size)
{
if(uart == NULL || !uart->rx_enabled)
return 0;
size_t nextPos = (rx_buffer->wpos + 1) % rx_buffer->size;
if (nextPos == rx_buffer->rpos)
{
uart->rx_overrun = true;
#ifdef UART_DISCARD_NEWEST
return;
#else
if (++rx_buffer->rpos == rx_buffer->size)
rx_buffer->rpos = 0;
#endif
}
rx_buffer->buffer[rx_buffer->wpos] = data;
rx_buffer->wpos = nextPos;
}
if(uart->rx_buffer->size == new_size)
return uart->rx_buffer->size;
// insert a new byte into the RX FIFO nuffer
void uart_new_data(const int uart_nr, uint8_t data)
{
uart_t* uart = UART[uart_nr];
uint8_t * new_buf = (uint8_t*)malloc(new_size);
if(!new_buf)
return uart->rx_buffer->size;
if (uart == NULL || !uart->rx_enabled)
{
return;
}
size_t new_wpos = 0;
// if uart_rx_available_unsafe() returns non-0, uart_read_char_unsafe() can't return -1
while(uart_rx_available_unsafe(uart->rx_buffer) && new_wpos < new_size)
new_buf[new_wpos++] = uart_read_char_unsafe(uart);
if (new_wpos == new_size)
new_wpos = 0;
uart_handle_data(uart, data);
}
uint8_t * old_buf = uart->rx_buffer->buffer;
uart->rx_buffer->rpos = 0;
uart->rx_buffer->wpos = new_wpos;
uart->rx_buffer->size = new_size;
uart->rx_buffer->buffer = new_buf;
free(old_buf);
return uart->rx_buffer->size;
}
static size_t uart_rx_available_unsafe(const struct uart_rx_buffer_* rx_buffer)
{
size_t ret = rx_buffer->wpos - rx_buffer->rpos;
size_t
uart_get_rx_buffer_size(uart_t* uart)
{
return uart && uart->rx_enabled ? uart->rx_buffer->size : 0;
}
if (rx_buffer->wpos < rx_buffer->rpos)
ret = (rx_buffer->wpos + rx_buffer->size) - rx_buffer->rpos;
size_t
uart_write_char(uart_t* uart, char c)
{
if(uart == NULL || !uart->tx_enabled)
return 0;
return ret;
}
uart_do_write_char(uart->uart_nr, c);
// taking data straight from fifo, only needed in uart_resize_rx_buffer()
static int uart_read_char_unsafe(uart_t* uart)
{
if (uart_rx_available_unsafe(uart->rx_buffer))
{
// take oldest sw data
int ret = uart->rx_buffer->buffer[uart->rx_buffer->rpos];
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + 1) % uart->rx_buffer->size;
return ret;
}
// unavailable
return -1;
}
return 1;
}
/**********************************************************/
/************ UART API FUNCTIONS **************************/
/**********************************************************/
size_t
uart_write(uart_t* uart, const char* buf, size_t size)
{
if(uart == NULL || !uart->tx_enabled)
return 0;
size_t uart_rx_available(uart_t* uart)
{
if (uart == NULL || !uart->rx_enabled)
return 0;
size_t ret = size;
const int uart_nr = uart->uart_nr;
while (size--)
uart_do_write_char(uart_nr, *buf++);
return uart_rx_available_unsafe(uart->rx_buffer);
}
return ret;
}
int uart_peek_char(uart_t* uart)
{
if (uart == NULL || !uart->rx_enabled)
return -1;
size_t
uart_tx_free(uart_t* uart)
{
if(uart == NULL || !uart->tx_enabled)
return 0;
if (!uart_rx_available_unsafe(uart->rx_buffer))
return -1;
return UART_TX_FIFO_SIZE;
}
return uart->rx_buffer->buffer[uart->rx_buffer->rpos];
}
void
uart_wait_tx_empty(uart_t* uart)
{
(void) uart;
}
int uart_read_char(uart_t* uart)
{
uint8_t ret;
return uart_read(uart, (char*)&ret, 1) ? ret : -1;
}
void
uart_flush(uart_t* uart)
{
if(uart == NULL)
return;
size_t uart_read(uart_t* uart, char* userbuffer, size_t usersize)
{
if (uart == NULL || !uart->rx_enabled)
return 0;
if(uart->rx_enabled)
{
uart->rx_buffer->rpos = 0;
uart->rx_buffer->wpos = 0;
}
}
if (!blocking_uart)
{
char c;
if (read(0, &c, 1) == 1)
uart_new_data(0, c);
}
void
uart_set_baudrate(uart_t* uart, int baud_rate)
{
if(uart == NULL)
return;
size_t ret = 0;
while (ret < usersize && uart_rx_available_unsafe(uart->rx_buffer))
{
// pour sw buffer to user's buffer
// get largest linear length from sw buffer
size_t chunk = uart->rx_buffer->rpos < uart->rx_buffer->wpos
? uart->rx_buffer->wpos - uart->rx_buffer->rpos
: uart->rx_buffer->size - uart->rx_buffer->rpos;
if (ret + chunk > usersize)
chunk = usersize - ret;
memcpy(userbuffer + ret, uart->rx_buffer->buffer + uart->rx_buffer->rpos, chunk);
uart->rx_buffer->rpos = (uart->rx_buffer->rpos + chunk) % uart->rx_buffer->size;
ret += chunk;
}
return ret;
}
uart->baud_rate = baud_rate;
}
size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size)
{
if (uart == NULL || !uart->rx_enabled)
return 0;
int
uart_get_baudrate(uart_t* uart)
{
if(uart == NULL)
return 0;
if (uart->rx_buffer->size == new_size)
return uart->rx_buffer->size;
return uart->baud_rate;
}
uint8_t* new_buf = (uint8_t*)malloc(new_size);
if (!new_buf)
return uart->rx_buffer->size;
uint8_t
uart_get_bit_length(const int uart_nr)
{
uint8_t width = ((uart_nr % 16) >> 2) + 5;
uint8_t parity = (uart_nr >> 5) + 1;
uint8_t stop = uart_nr % 4;
return (width + parity + stop + 1);
}
size_t new_wpos = 0;
// if uart_rx_available_unsafe() returns non-0, uart_read_char_unsafe() can't return -1
while (uart_rx_available_unsafe(uart->rx_buffer) && new_wpos < new_size)
new_buf[new_wpos++] = uart_read_char_unsafe(uart);
if (new_wpos == new_size)
new_wpos = 0;
uart_t*
uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size, bool invert)
{
(void) config;
(void) tx_pin;
(void) invert;
uart_t* uart = (uart_t*) malloc(sizeof(uart_t));
if(uart == NULL)
return NULL;
uint8_t* old_buf = uart->rx_buffer->buffer;
uart->rx_buffer->rpos = 0;
uart->rx_buffer->wpos = new_wpos;
uart->rx_buffer->size = new_size;
uart->rx_buffer->buffer = new_buf;
free(old_buf);
return uart->rx_buffer->size;
}
uart->uart_nr = uart_nr;
uart->rx_overrun = false;
size_t uart_get_rx_buffer_size(uart_t* uart)
{
return uart && uart->rx_enabled ? uart->rx_buffer->size : 0;
}
switch(uart->uart_nr)
{
case UART0:
uart->rx_enabled = (mode != UART_TX_ONLY);
uart->tx_enabled = (mode != UART_RX_ONLY);
if(uart->rx_enabled)
{
struct uart_rx_buffer_ * rx_buffer = (struct uart_rx_buffer_ *)malloc(sizeof(struct uart_rx_buffer_));
if(rx_buffer == NULL)
{
free(uart);
return NULL;
}
rx_buffer->size = rx_size;//var this
rx_buffer->rpos = 0;
rx_buffer->wpos = 0;
rx_buffer->buffer = (uint8_t *)malloc(rx_buffer->size);
if(rx_buffer->buffer == NULL)
{
free(rx_buffer);
free(uart);
return NULL;
}
uart->rx_buffer = rx_buffer;
}
break;
size_t uart_write_char(uart_t* uart, char c)
{
if (uart == NULL || !uart->tx_enabled)
return 0;
case UART1:
// Note: uart_interrupt_handler does not support RX on UART 1.
uart->rx_enabled = false;
uart->tx_enabled = (mode != UART_RX_ONLY);
break;
uart_do_write_char(uart->uart_nr, c);
case UART_NO:
default:
// big fail!
free(uart);
return NULL;
}
return 1;
}
uart_set_baudrate(uart, baudrate);
size_t uart_write(uart_t* uart, const char* buf, size_t size)
{
if (uart == NULL || !uart->tx_enabled)
return 0;
UART[uart_nr] = uart;
size_t ret = size;
const int uart_nr = uart->uart_nr;
while (size--)
uart_do_write_char(uart_nr, *buf++);
return uart;
}
return ret;
}
void
uart_uninit(uart_t* uart)
{
if(uart == NULL)
return;
size_t uart_tx_free(uart_t* uart)
{
if (uart == NULL || !uart->tx_enabled)
return 0;
if(uart->rx_enabled) {
free(uart->rx_buffer->buffer);
free(uart->rx_buffer);
}
free(uart);
}
return UART_TX_FIFO_SIZE;
}
bool
uart_swap(uart_t* uart, int tx_pin)
{
(void) uart;
(void) tx_pin;
return true;
}
void uart_wait_tx_empty(uart_t* uart)
{
(void)uart;
}
bool
uart_set_tx(uart_t* uart, int tx_pin)
{
(void) uart;
(void) tx_pin;
return true;
}
void uart_flush(uart_t* uart)
{
if (uart == NULL)
return;
bool
uart_set_pins(uart_t* uart, int tx, int rx)
{
(void) uart;
(void) tx;
(void) rx;
return true;
}
if (uart->rx_enabled)
{
uart->rx_buffer->rpos = 0;
uart->rx_buffer->wpos = 0;
}
}
bool
uart_tx_enabled(uart_t* uart)
{
if(uart == NULL)
return false;
void uart_set_baudrate(uart_t* uart, int baud_rate)
{
if (uart == NULL)
return;
return uart->tx_enabled;
}
uart->baud_rate = baud_rate;
}
bool
uart_rx_enabled(uart_t* uart)
{
if(uart == NULL)
return false;
int uart_get_baudrate(uart_t* uart)
{
if (uart == NULL)
return 0;
return uart->rx_enabled;
}
return uart->baud_rate;
}
bool
uart_has_overrun(uart_t* uart)
{
if(uart == NULL || !uart->rx_overrun)
return false;
uint8_t uart_get_bit_length(const int uart_nr)
{
uint8_t width = ((uart_nr % 16) >> 2) + 5;
uint8_t parity = (uart_nr >> 5) + 1;
uint8_t stop = uart_nr % 4;
return (width + parity + stop + 1);
}
// clear flag
uart->rx_overrun = false;
return true;
}
uart_t* uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size,
bool invert)
{
(void)config;
(void)tx_pin;
(void)invert;
uart_t* uart = (uart_t*)malloc(sizeof(uart_t));
if (uart == NULL)
return NULL;
bool
uart_has_rx_error(uart_t* uart)
{
(void) uart;
return false;
}
uart->uart_nr = uart_nr;
uart->rx_overrun = false;
void
uart_set_debug(int uart_nr)
{
(void)uart_nr;
}
switch (uart->uart_nr)
{
case UART0:
uart->rx_enabled = (mode != UART_TX_ONLY);
uart->tx_enabled = (mode != UART_RX_ONLY);
if (uart->rx_enabled)
{
struct uart_rx_buffer_* rx_buffer
= (struct uart_rx_buffer_*)malloc(sizeof(struct uart_rx_buffer_));
if (rx_buffer == NULL)
{
free(uart);
return NULL;
}
rx_buffer->size = rx_size; // var this
rx_buffer->rpos = 0;
rx_buffer->wpos = 0;
rx_buffer->buffer = (uint8_t*)malloc(rx_buffer->size);
if (rx_buffer->buffer == NULL)
{
free(rx_buffer);
free(uart);
return NULL;
}
uart->rx_buffer = rx_buffer;
}
break;
int
uart_get_debug()
{
return s_uart_debug_nr;
}
case UART1:
// Note: uart_interrupt_handler does not support RX on UART 1.
uart->rx_enabled = false;
uart->tx_enabled = (mode != UART_RX_ONLY);
break;
void
uart_start_detect_baudrate(int uart_nr)
{
(void) uart_nr;
}
case UART_NO:
default:
// big fail!
free(uart);
return NULL;
}
int
uart_detect_baudrate(int uart_nr)
{
(void) uart_nr;
return 115200;
}
uart_set_baudrate(uart, baudrate);
UART[uart_nr] = uart;
return uart;
}
void uart_uninit(uart_t* uart)
{
if (uart == NULL)
return;
if (uart->rx_enabled)
{
free(uart->rx_buffer->buffer);
free(uart->rx_buffer);
}
free(uart);
}
bool uart_swap(uart_t* uart, int tx_pin)
{
(void)uart;
(void)tx_pin;
return true;
}
bool uart_set_tx(uart_t* uart, int tx_pin)
{
(void)uart;
(void)tx_pin;
return true;
}
bool uart_set_pins(uart_t* uart, int tx, int rx)
{
(void)uart;
(void)tx;
(void)rx;
return true;
}
bool uart_tx_enabled(uart_t* uart)
{
if (uart == NULL)
return false;
return uart->tx_enabled;
}
bool uart_rx_enabled(uart_t* uart)
{
if (uart == NULL)
return false;
return uart->rx_enabled;
}
bool uart_has_overrun(uart_t* uart)
{
if (uart == NULL || !uart->rx_overrun)
return false;
// clear flag
uart->rx_overrun = false;
return true;
}
bool uart_has_rx_error(uart_t* uart)
{
(void)uart;
return false;
}
void uart_set_debug(int uart_nr)
{
(void)uart_nr;
}
int uart_get_debug()
{
return s_uart_debug_nr;
}
void uart_start_detect_baudrate(int uart_nr)
{
(void)uart_nr;
}
int uart_detect_baudrate(int uart_nr)
{
(void)uart_nr;
return 115200;
}
};
size_t uart_peek_available (uart_t* uart) { return 0; }
const char* uart_peek_buffer (uart_t* uart) { return nullptr; }
void uart_peek_consume (uart_t* uart, size_t consume) { (void)uart; (void)consume; }
size_t uart_peek_available(uart_t* uart)
{
return 0;
}
const char* uart_peek_buffer(uart_t* uart)
{
return nullptr;
}
void uart_peek_consume(uart_t* uart, size_t consume)
{
(void)uart;
(void)consume;
}

View File

@ -44,32 +44,31 @@ extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
// lwIP API side of WiFiServer
WiFiServer::WiFiServer (const IPAddress& addr, uint16_t port)
WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port)
{
(void)addr;
_port = port;
(void)addr;
_port = port;
}
WiFiServer::WiFiServer (uint16_t port)
WiFiServer::WiFiServer(uint16_t port)
{
_port = port;
_port = port;
}
WiFiClient WiFiServer::available (uint8_t* status)
WiFiClient WiFiServer::available(uint8_t* status)
{
(void)status;
return accept();
(void)status;
return accept();
}
WiFiClient WiFiServer::accept ()
WiFiClient WiFiServer::accept()
{
if (hasClient())
return WiFiClient(new ClientContext(serverAccept(pcb2int(_listen_pcb))));
return WiFiClient();
if (hasClient())
return WiFiClient(new ClientContext(serverAccept(pcb2int(_listen_pcb))));
return WiFiClient();
}
// static declaration
#include <include/UdpContext.h>
uint32_t UdpContext::staticMCastAddr = 0;

View File

@ -44,26 +44,26 @@
// host socket internal side of WiFiServer
int serverAccept (int srvsock)
int serverAccept(int srvsock)
{
int clisock;
socklen_t n;
struct sockaddr_in client;
n = sizeof(client);
if ((clisock = accept(srvsock, (struct sockaddr*)&client, &n)) == -1)
{
perror(MOCK "accept()");
exit(EXIT_FAILURE);
}
return mockSockSetup(clisock);
int clisock;
socklen_t n;
struct sockaddr_in client;
n = sizeof(client);
if ((clisock = accept(srvsock, (struct sockaddr*)&client, &n)) == -1)
{
perror(MOCK "accept()");
exit(EXIT_FAILURE);
}
return mockSockSetup(clisock);
}
void WiFiServer::begin (uint16_t port)
void WiFiServer::begin(uint16_t port)
{
return begin(port, !0);
}
void WiFiServer::begin (uint16_t port, uint8_t backlog)
void WiFiServer::begin(uint16_t port, uint8_t backlog)
{
if (!backlog)
return;
@ -71,85 +71,86 @@ void WiFiServer::begin (uint16_t port, uint8_t backlog)
return begin();
}
void WiFiServer::begin ()
void WiFiServer::begin()
{
int sock;
int mockport;
struct sockaddr_in server;
int sock;
int mockport;
struct sockaddr_in server;
mockport = _port;
if (mockport < 1024 && mock_port_shifter)
{
mockport += mock_port_shifter;
fprintf(stderr, MOCK "=====> WiFiServer port: %d shifted to %d (use option -s) <=====\n", _port, mockport);
}
else
fprintf(stderr, MOCK "=====> WiFiServer port: %d <=====\n", mockport);
mockport = _port;
if (mockport < 1024 && mock_port_shifter)
{
mockport += mock_port_shifter;
fprintf(stderr, MOCK "=====> WiFiServer port: %d shifted to %d (use option -s) <=====\n",
_port, mockport);
}
else
fprintf(stderr, MOCK "=====> WiFiServer port: %d <=====\n", mockport);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror(MOCK "socket()");
exit(EXIT_FAILURE);
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror(MOCK "socket()");
exit(EXIT_FAILURE);
}
int optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
{
perror(MOCK "reuseport");
exit(EXIT_FAILURE);
}
int optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
{
perror(MOCK "reuseport");
exit(EXIT_FAILURE);
}
server.sin_family = AF_INET;
server.sin_port = htons(mockport);
server.sin_addr.s_addr = htonl(global_source_address);
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
{
perror(MOCK "bind()");
exit(EXIT_FAILURE);
}
server.sin_family = AF_INET;
server.sin_port = htons(mockport);
server.sin_addr.s_addr = htonl(global_source_address);
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
{
perror(MOCK "bind()");
exit(EXIT_FAILURE);
}
if (listen(sock, 1) == -1)
{
perror(MOCK "listen()");
exit(EXIT_FAILURE);
}
if (listen(sock, 1) == -1)
{
perror(MOCK "listen()");
exit(EXIT_FAILURE);
}
// store int into pointer
_listen_pcb = int2pcb(sock);
// store int into pointer
_listen_pcb = int2pcb(sock);
}
bool WiFiServer::hasClient ()
bool WiFiServer::hasClient()
{
struct pollfd p;
p.fd = pcb2int(_listen_pcb);
p.events = POLLIN;
return poll(&p, 1, 0) && p.revents == POLLIN;
struct pollfd p;
p.fd = pcb2int(_listen_pcb);
p.events = POLLIN;
return poll(&p, 1, 0) && p.revents == POLLIN;
}
void WiFiServer::close ()
void WiFiServer::close()
{
if (pcb2int(_listen_pcb) >= 0)
::close(pcb2int(_listen_pcb));
_listen_pcb = int2pcb(-1);
if (pcb2int(_listen_pcb) >= 0)
::close(pcb2int(_listen_pcb));
_listen_pcb = int2pcb(-1);
}
void WiFiServer::stop ()
void WiFiServer::stop()
{
close();
}
size_t WiFiServer::hasClientData ()
size_t WiFiServer::hasClientData()
{
// Trivial Mocking:
// There is no waiting list of clients in this trivial mocking code,
// so the code has to act as if the tcp backlog list is full,
// and nothing is known about potential further clients.
// It could be implemented by accepting new clients and store their data until the current one is closed.
// It could be implemented by accepting new clients and store their data until the current one
// is closed.
return 0;
}
bool WiFiServer::hasMaxPendingClients ()
bool WiFiServer::hasMaxPendingClients()
{
// Mocking code does not consider the waiting client list,
// so it will return ::hasClient() here meaning:

View File

@ -7,58 +7,54 @@ esp8266::AddressListImplementation::AddressList addrList;
extern "C"
{
extern netif netif0;
extern netif netif0;
netif* netif_list = &netif0;
netif* netif_list = &netif0;
err_t dhcp_renew(struct netif* netif)
{
(void)netif;
return ERR_OK;
}
err_t dhcp_renew(struct netif *netif)
{
(void)netif;
return ERR_OK;
}
void sntp_setserver(u8_t, const ip_addr_t) { }
void sntp_setserver(u8_t, const ip_addr_t)
{
}
const ip_addr_t* sntp_getserver(u8_t)
{
return IP_ADDR_ANY;
}
const ip_addr_t* sntp_getserver(u8_t)
{
return IP_ADDR_ANY;
}
err_t etharp_request(struct netif* netif, const ip4_addr_t* ipaddr)
{
(void)netif;
(void)ipaddr;
return ERR_OK;
}
err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
{
(void)netif;
(void)ipaddr;
return ERR_OK;
}
err_t igmp_start(struct netif* netif)
{
(void)netif;
return ERR_OK;
}
err_t igmp_start(struct netif* netif)
{
(void)netif;
return ERR_OK;
}
err_t igmp_joingroup_netif(struct netif* netif, const ip4_addr_t* groupaddr)
{
(void)netif;
(void)groupaddr;
return ERR_OK;
}
err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
{
(void)netif;
(void)groupaddr;
return ERR_OK;
}
err_t igmp_leavegroup_netif(struct netif* netif, const ip4_addr_t* groupaddr)
{
(void)netif;
(void)groupaddr;
return ERR_OK;
}
err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
{
(void)netif;
(void)groupaddr;
return ERR_OK;
}
struct netif* netif_get_by_index(u8_t idx)
{
(void)idx;
return &netif0;
}
struct netif* netif_get_by_index(u8_t idx)
{
(void)idx;
return &netif0;
}
} // extern "C"
} // extern "C"

View File

@ -4,12 +4,11 @@
extern "C"
{
#include <user_interface.h>
#include <lwip/netif.h>
extern netif netif0;
extern netif netif0;
} // extern "C"
} // extern "C"
#endif // __MOCKLWIP_H
#endif // __MOCKLWIP_H

View File

@ -39,176 +39,189 @@
#include <assert.h>
#include <net/if.h>
int mockUDPSocket ()
int mockUDPSocket()
{
int s;
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1 || fcntl(s, F_SETFL, O_NONBLOCK) == -1)
{
fprintf(stderr, MOCK "UDP socket: %s", strerror(errno));
exit(EXIT_FAILURE);
}
return s;
int s;
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1 || fcntl(s, F_SETFL, O_NONBLOCK) == -1)
{
fprintf(stderr, MOCK "UDP socket: %s", strerror(errno));
exit(EXIT_FAILURE);
}
return s;
}
bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
bool mockUDPListen(int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
{
int optval;
int mockport;
int optval;
int mockport;
mockport = port;
if (mockport < 1024 && mock_port_shifter)
{
mockport += mock_port_shifter;
fprintf(stderr, MOCK "=====> UdpServer port: %d shifted to %d (use option -s) <=====\n", port, mockport);
}
else
fprintf(stderr, MOCK "=====> UdpServer port: %d <=====\n", mockport);
mockport = port;
if (mockport < 1024 && mock_port_shifter)
{
mockport += mock_port_shifter;
fprintf(stderr, MOCK "=====> UdpServer port: %d shifted to %d (use option -s) <=====\n",
port, mockport);
}
else
fprintf(stderr, MOCK "=====> UdpServer port: %d <=====\n", mockport);
optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
fprintf(stderr, MOCK "SO_REUSEPORT failed\n");
optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
fprintf(stderr, MOCK "SO_REUSEADDR failed\n");
optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
fprintf(stderr, MOCK "SO_REUSEPORT failed\n");
optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
fprintf(stderr, MOCK "SO_REUSEADDR failed\n");
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
(void) dstaddr;
//servaddr.sin_addr.s_addr = htonl(global_source_address);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(mockport);
// Filling server information
servaddr.sin_family = AF_INET;
(void)dstaddr;
// servaddr.sin_addr.s_addr = htonl(global_source_address);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(mockport);
// Bind the socket with the server address
if (bind(sock, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
fprintf(stderr, MOCK "UDP bind on port %d failed: %s\n", mockport, strerror(errno));
return false;
}
else
mockverbose("UDP server on port %d (sock=%d)\n", mockport, sock);
// Bind the socket with the server address
if (bind(sock, (const struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
{
fprintf(stderr, MOCK "UDP bind on port %d failed: %s\n", mockport, strerror(errno));
return false;
}
else
mockverbose("UDP server on port %d (sock=%d)\n", mockport, sock);
if (!mcast)
mcast = inet_addr("224.0.0.1"); // all hosts group
if (mcast)
{
// https://web.cs.wpi.edu/~claypool/courses/4514-B99/samples/multicast.c
// https://stackoverflow.com/questions/12681097/c-choose-interface-for-udp-multicast-socket
if (!mcast)
mcast = inet_addr("224.0.0.1"); // all hosts group
if (mcast)
{
// https://web.cs.wpi.edu/~claypool/courses/4514-B99/samples/multicast.c
// https://stackoverflow.com/questions/12681097/c-choose-interface-for-udp-multicast-socket
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = mcast;
//mreq.imr_interface.s_addr = htonl(global_source_address);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = mcast;
// mreq.imr_interface.s_addr = htonl(global_source_address);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (host_interface)
{
if (host_interface)
{
#if __APPLE__
int idx = if_nametoindex(host_interface);
if (setsockopt(sock, IPPROTO_TCP, IP_BOUND_IF, &idx, sizeof(idx)) == -1)
int idx = if_nametoindex(host_interface);
if (setsockopt(sock, IPPROTO_TCP, IP_BOUND_IF, &idx, sizeof(idx)) == -1)
#else
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, host_interface, strlen(host_interface)) == -1)
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, host_interface,
strlen(host_interface))
== -1)
#endif
fprintf(stderr, MOCK "UDP multicast: can't setup bind/output on interface %s: %s\n", host_interface, strerror(errno));
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mreq.imr_interface, sizeof(struct in_addr)) == -1)
fprintf(stderr, MOCK "UDP multicast: can't setup bind/input on interface %s: %s\n", host_interface, strerror(errno));
}
fprintf(stderr, MOCK "UDP multicast: can't setup bind/output on interface %s: %s\n",
host_interface, strerror(errno));
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mreq.imr_interface,
sizeof(struct in_addr))
== -1)
fprintf(stderr, MOCK "UDP multicast: can't setup bind/input on interface %s: %s\n",
host_interface, strerror(errno));
}
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
fprintf(stderr, MOCK "can't join multicast group addr %08x\n", (int)mcast);
return false;
}
else
mockverbose("joined multicast group addr %08lx\n", (long)ntohl(mcast));
}
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
fprintf(stderr, MOCK "can't join multicast group addr %08x\n", (int)mcast);
return false;
}
else
mockverbose("joined multicast group addr %08lx\n", (long)ntohl(mcast));
}
return true;
return true;
}
size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port)
size_t mockUDPFillInBuf(int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize,
uint8_t addr[16], uint16_t& port)
{
struct sockaddr_storage addrbuf;
socklen_t addrbufsize = std::min((socklen_t)sizeof(addrbuf), (socklen_t)16);
struct sockaddr_storage addrbuf;
socklen_t addrbufsize = std::min((socklen_t)sizeof(addrbuf), (socklen_t)16);
size_t maxread = CCBUFSIZE - ccinbufsize;
ssize_t ret = ::recvfrom(sock, ccinbuf + ccinbufsize, maxread, 0/*flags*/, (sockaddr*)&addrbuf, &addrbufsize);
if (ret == -1)
{
if (errno != EAGAIN)
fprintf(stderr, MOCK "UDPContext::(read/peek): filling buffer for %zd bytes: %s\n", maxread, strerror(errno));
ret = 0;
}
size_t maxread = CCBUFSIZE - ccinbufsize;
ssize_t ret = ::recvfrom(sock, ccinbuf + ccinbufsize, maxread, 0 /*flags*/, (sockaddr*)&addrbuf,
&addrbufsize);
if (ret == -1)
{
if (errno != EAGAIN)
fprintf(stderr, MOCK "UDPContext::(read/peek): filling buffer for %zd bytes: %s\n",
maxread, strerror(errno));
ret = 0;
}
if (ret > 0)
{
port = ntohs(((sockaddr_in*)&addrbuf)->sin_port);
if (addrbuf.ss_family == AF_INET)
memcpy(&addr[0], &(((sockaddr_in*)&addrbuf)->sin_addr.s_addr), addrsize = 4);
else
{
fprintf(stderr, MOCK "TODO UDP+IPv6\n");
exit(EXIT_FAILURE);
}
}
if (ret > 0)
{
port = ntohs(((sockaddr_in*)&addrbuf)->sin_port);
if (addrbuf.ss_family == AF_INET)
memcpy(&addr[0], &(((sockaddr_in*)&addrbuf)->sin_addr.s_addr), addrsize = 4);
else
{
fprintf(stderr, MOCK "TODO UDP+IPv6\n");
exit(EXIT_FAILURE);
}
}
return ccinbufsize += ret;
return ccinbufsize += ret;
}
size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
size_t mockUDPPeekBytes(int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf,
size_t& ccinbufsize)
{
(void) sock;
(void) timeout_ms;
if (usersize > CCBUFSIZE)
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
(void)sock;
(void)timeout_ms;
if (usersize > CCBUFSIZE)
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE,
usersize - CCBUFSIZE, usersize);
size_t retsize = 0;
if (ccinbufsize)
{
// data already buffered
retsize = usersize;
if (retsize > ccinbufsize)
retsize = ccinbufsize;
}
memcpy(dst, ccinbuf, retsize);
return retsize;
size_t retsize = 0;
if (ccinbufsize)
{
// data already buffered
retsize = usersize;
if (retsize > ccinbufsize)
retsize = ccinbufsize;
}
memcpy(dst, ccinbuf, retsize);
return retsize;
}
void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize)
void mockUDPSwallow(size_t copied, char* ccinbuf, size_t& ccinbufsize)
{
// poor man buffer
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
ccinbufsize -= copied;
// poor man buffer
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
ccinbufsize -= copied;
}
size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
size_t mockUDPRead(int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf,
size_t& ccinbufsize)
{
size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
mockUDPSwallow(copied, ccinbuf, ccinbufsize);
return copied;
size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
mockUDPSwallow(copied, ccinbuf, ccinbufsize);
return copied;
}
size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port)
size_t mockUDPWrite(int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4,
uint16_t port)
{
(void) timeout_ms;
// Filling server information
struct sockaddr_in peer;
peer.sin_family = AF_INET;
peer.sin_addr.s_addr = ipv4; //XXFIXME should use lwip_htonl?
peer.sin_port = htons(port);
int ret = ::sendto(sock, data, size, 0/*flags*/, (const sockaddr*)&peer, sizeof(peer));
if (ret == -1)
{
fprintf(stderr, MOCK "UDPContext::write: write(%d): %s\n", sock, strerror(errno));
return 0;
}
if (ret != (int)size)
{
fprintf(stderr, MOCK "UDPContext::write: short write (%d < %zd) (TODO)\n", ret, size);
exit(EXIT_FAILURE);
}
(void)timeout_ms;
// Filling server information
struct sockaddr_in peer;
peer.sin_family = AF_INET;
peer.sin_addr.s_addr = ipv4; // XXFIXME should use lwip_htonl?
peer.sin_port = htons(port);
int ret = ::sendto(sock, data, size, 0 /*flags*/, (const sockaddr*)&peer, sizeof(peer));
if (ret == -1)
{
fprintf(stderr, MOCK "UDPContext::write: write(%d): %s\n", sock, strerror(errno));
return 0;
}
if (ret != (int)size)
{
fprintf(stderr, MOCK "UDPContext::write: short write (%d < %zd) (TODO)\n", ret, size);
exit(EXIT_FAILURE);
}
return ret;
return ret;
}

View File

@ -4,59 +4,69 @@
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-06 Hernando Barragan
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
extern "C" {
extern "C"
{
#include <stdlib.h>
#include <stdint.h>
}
void randomSeed(unsigned long seed) {
if(seed != 0) {
void randomSeed(unsigned long seed)
{
if (seed != 0)
{
srand(seed);
}
}
long random(long howbig) {
if(howbig == 0) {
long random(long howbig)
{
if (howbig == 0)
{
return 0;
}
return (rand()) % howbig;
}
long random(long howsmall, long howbig) {
if(howsmall >= howbig) {
long random(long howsmall, long howbig)
{
if (howsmall >= howbig)
{
return howsmall;
}
long diff = howbig - howsmall;
return random(diff) + howsmall;
}
long map(long x, long in_min, long in_max, long out_min, long out_max) {
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
uint16_t makeWord(unsigned int w) {
uint16_t makeWord(unsigned int w)
{
return w;
}
uint16_t makeWord(unsigned char h, unsigned char l) {
uint16_t makeWord(unsigned char h, unsigned char l)
{
return (h << 8) | l;
}

View File

@ -36,45 +36,46 @@
#include <stdarg.h>
#include <sys/cdefs.h>
typedef signed char sint8_t;
typedef signed short sint16_t;
typedef signed long sint32_t;
typedef signed long long sint64_t;
typedef signed char sint8_t;
typedef signed short sint16_t;
typedef signed long sint32_t;
typedef signed long long sint64_t;
// CONFLICT typedef unsigned long long u_int64_t;
typedef float real32_t;
typedef double real64_t;
typedef float real32_t;
typedef double real64_t;
// CONFLICT typedef unsigned char uint8;
typedef unsigned char u8;
typedef signed char sint8;
typedef signed char int8;
typedef signed char s8;
typedef unsigned short uint16;
typedef unsigned short u16;
typedef signed short sint16;
typedef signed short s16;
typedef unsigned char u8;
typedef signed char sint8;
typedef signed char int8;
typedef signed char s8;
typedef unsigned short uint16;
typedef unsigned short u16;
typedef signed short sint16;
typedef signed short s16;
// CONFLICT typedef unsigned int uint32;
typedef unsigned int u_int;
typedef unsigned int u32;
typedef signed int sint32;
typedef signed int s32;
typedef int int32;
typedef signed long long sint64;
typedef unsigned long long uint64;
typedef unsigned long long u64;
typedef float real32;
typedef double real64;
typedef unsigned int u_int;
typedef unsigned int u32;
typedef signed int sint32;
typedef signed int s32;
typedef int int32;
typedef signed long long sint64;
typedef unsigned long long uint64;
typedef unsigned long long u64;
typedef float real32;
typedef double real64;
#define __le16 u16
#define __le16 u16
#define LOCAL static
#define LOCAL static
#ifndef NULL
#define NULL (void *)0
#define NULL (void*)0
#endif /* NULL */
/* probably should not put STATUS here */
typedef enum {
typedef enum
{
OK = 0,
FAIL,
PENDING,
@ -82,10 +83,10 @@ typedef enum {
CANCEL,
} STATUS;
#define BIT(nr) (1UL << (nr))
#define BIT(nr) (1UL << (nr))
#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
#define DMEM_ATTR __attribute__((section(".bss")))
#define SHMEM_ATTR
@ -93,9 +94,15 @@ typedef enum {
#ifdef ICACHE_FLASH
#define __ICACHE_STRINGIZE_NX(A) #A
#define __ICACHE_STRINGIZE(A) __ICACHE_STRINGIZE_NX(A)
#define ICACHE_FLASH_ATTR __attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
#define IRAM_ATTR __attribute__((section("\".iram.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
#define ICACHE_RODATA_ATTR __attribute__((section("\".irom.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
#define ICACHE_FLASH_ATTR \
__attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE( \
__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
#define IRAM_ATTR \
__attribute__((section("\".iram.text." __FILE__ "." __ICACHE_STRINGIZE( \
__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
#define ICACHE_RODATA_ATTR \
__attribute__((section("\".irom.text." __FILE__ "." __ICACHE_STRINGIZE( \
__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
#else
#define ICACHE_FLASH_ATTR
#define IRAM_ATTR
@ -108,10 +115,9 @@ typedef enum {
#define STORE_ATTR __attribute__((aligned(4)))
#ifndef __cplusplus
#define BOOL bool
#define TRUE true
#define FALSE false
#define BOOL bool
#define TRUE true
#define FALSE false
#endif /* !__cplusplus */

View File

@ -2,8 +2,8 @@
#ifndef FAKE_ESP8266_PERI_H
#define FAKE_ESP8266_PERI_H
const int GPI = 0;
const int GPO = 0;
const int GPI = 0;
const int GPO = 0;
const int GP16I = 0;
#endif

View File

@ -11,17 +11,15 @@
extern "C"
{
extern uint32_t s_phys_addr;
extern uint32_t s_phys_size;
extern uint32_t s_phys_page;
extern uint32_t s_phys_block;
extern uint8_t* s_phys_data;
extern uint32_t s_phys_addr;
extern uint32_t s_phys_size;
extern uint32_t s_phys_page;
extern uint32_t s_phys_block;
extern uint8_t* s_phys_data;
extern int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst);
extern int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t *src);
extern int32_t flash_hal_erase(uint32_t addr, uint32_t size);
extern int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t* dst);
extern int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t* src);
extern int32_t flash_hal_erase(uint32_t addr, uint32_t size);
}
#endif

View File

@ -7,31 +7,35 @@
extern "C"
{
uint32_t s_phys_addr = 0;
uint32_t s_phys_size = 0;
uint32_t s_phys_page = 0;
uint32_t s_phys_addr = 0;
uint32_t s_phys_size = 0;
uint32_t s_phys_page = 0;
uint32_t s_phys_block = 0;
uint8_t* s_phys_data = nullptr;
uint8_t* s_phys_data = nullptr;
}
int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t* dst)
{
memcpy(dst, s_phys_data + addr, size);
return 0;
}
int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t *src) {
int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t* src)
{
memcpy(s_phys_data + addr, src, size);
return 0;
}
int32_t flash_hal_erase(uint32_t addr, uint32_t size) {
if ((size & (FLASH_SECTOR_SIZE - 1)) != 0 ||
(addr & (FLASH_SECTOR_SIZE - 1)) != 0) {
int32_t flash_hal_erase(uint32_t addr, uint32_t size)
{
if ((size & (FLASH_SECTOR_SIZE - 1)) != 0 || (addr & (FLASH_SECTOR_SIZE - 1)) != 0)
{
abort();
}
const uint32_t sector = addr / FLASH_SECTOR_SIZE;
const uint32_t sector = addr / FLASH_SECTOR_SIZE;
const uint32_t sectorCount = size / FLASH_SECTOR_SIZE;
for (uint32_t i = 0; i < sectorCount; ++i) {
for (uint32_t i = 0; i < sectorCount; ++i)
{
memset(s_phys_data + (sector + i) * FLASH_SECTOR_SIZE, 0xff, FLASH_SECTOR_SIZE);
}
return 0;

View File

@ -26,7 +26,7 @@ class WiFiClient;
#include <assert.h>
bool getDefaultPrivateGlobalSyncValue ();
bool getDefaultPrivateGlobalSyncValue();
typedef void (*discard_cb_t)(void*, ClientContext*);
@ -39,19 +39,19 @@ public:
{
(void)pcb;
}
ClientContext (int sock) :
ClientContext(int sock) :
_discard_cb(nullptr), _discard_cb_arg(nullptr), _refcnt(0), _next(nullptr),
_sync(::getDefaultPrivateGlobalSyncValue()), _sock(sock)
{
}
err_t abort()
{
if (_sock >= 0)
{
::close(_sock);
mockverbose("socket %d closed\n", _sock);
mockverbose("socket %d closed\n", _sock);
}
_sock = -1;
return ERR_ABRT;
@ -88,11 +88,12 @@ public:
void unref()
{
DEBUGV(":ur %d\r\n", _refcnt);
if(--_refcnt == 0) {
if (--_refcnt == 0)
{
discard_received();
close();
if (_discard_cb)
_discard_cb(_discard_cb_arg, this);
_discard_cb(_discard_cb_arg, this);
DEBUGV(":del\r\n");
delete this;
}
@ -172,10 +173,10 @@ public:
int read()
{
char c;
return read(&c, 1)? (unsigned char)c: -1;
return read(&c, 1) ? (unsigned char)c : -1;
}
size_t read (char* dst, size_t size)
size_t read(char* dst, size_t size)
{
ssize_t ret = mockRead(_sock, dst, size, 0, _inbuf, _inbufsize);
if (ret < 0)
@ -189,10 +190,10 @@ public:
int peek()
{
char c;
return peekBytes(&c, 1)? c: -1;
return peekBytes(&c, 1) ? c : -1;
}
size_t peekBytes(char *dst, size_t size)
size_t peekBytes(char* dst, size_t size)
{
ssize_t ret = mockPeekBytes(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize);
if (ret < 0)
@ -216,60 +217,62 @@ public:
uint8_t state()
{
(void)getSize(); // read on socket to force detect closed peer
return _sock >= 0? ESTABLISHED: CLOSED;
(void)getSize(); // read on socket to force detect closed peer
return _sock >= 0 ? ESTABLISHED : CLOSED;
}
size_t write(const char* data, size_t size)
{
ssize_t ret = mockWrite(_sock, (const uint8_t*)data, size, _timeout_ms);
if (ret < 0)
{
abort();
return 0;
}
return ret;
ssize_t ret = mockWrite(_sock, (const uint8_t*)data, size, _timeout_ms);
if (ret < 0)
{
abort();
return 0;
}
return ret;
}
void keepAlive (uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC, uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC, uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT)
void keepAlive(uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC,
uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC,
uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT)
{
(void) idle_sec;
(void) intv_sec;
(void) count;
(void)idle_sec;
(void)intv_sec;
(void)count;
mockverbose("TODO ClientContext::keepAlive()\n");
}
bool isKeepAliveEnabled () const
bool isKeepAliveEnabled() const
{
mockverbose("TODO ClientContext::isKeepAliveEnabled()\n");
return false;
}
uint16_t getKeepAliveIdle () const
uint16_t getKeepAliveIdle() const
{
mockverbose("TODO ClientContext::getKeepAliveIdle()\n");
return 0;
}
uint16_t getKeepAliveInterval () const
uint16_t getKeepAliveInterval() const
{
mockverbose("TODO ClientContext::getKeepAliveInternal()\n");
return 0;
}
uint8_t getKeepAliveCount () const
uint8_t getKeepAliveCount() const
{
mockverbose("TODO ClientContext::getKeepAliveCount()\n");
return 0;
}
bool getSync () const
bool getSync() const
{
mockverbose("TODO ClientContext::getSync()\n");
return _sync;
}
void setSync (bool sync)
void setSync(bool sync)
{
mockverbose("TODO ClientContext::setSync()\n");
_sync = sync;
@ -277,13 +280,13 @@ public:
// return a pointer to available data buffer (size = peekAvailable())
// semantic forbids any kind of read() before calling peekConsume()
const char* peekBuffer ()
const char* peekBuffer()
{
return _inbuf;
}
// return number of byte accessible by peekBuffer()
size_t peekAvailable ()
size_t peekAvailable()
{
ssize_t ret = mockPeekBytes(_sock, nullptr, 0, 0, _inbuf, _inbufsize);
if (ret < 0)
@ -295,7 +298,7 @@ public:
}
// consume bytes after use (see peekBuffer)
void peekConsume (size_t consume)
void peekConsume(size_t consume)
{
assert(consume <= _inbufsize);
memmove(_inbuf, _inbuf + consume, _inbufsize - consume);
@ -303,22 +306,21 @@ public:
}
private:
discard_cb_t _discard_cb = nullptr;
void* _discard_cb_arg = nullptr;
discard_cb_t _discard_cb = nullptr;
void* _discard_cb_arg = nullptr;
int8_t _refcnt;
int8_t _refcnt;
ClientContext* _next;
bool _sync;
// MOCK
int _sock = -1;
int _sock = -1;
int _timeout_ms = 5000;
char _inbuf [CCBUFSIZE];
char _inbuf[CCBUFSIZE];
size_t _inbufsize = 0;
};
#endif //CLIENTCONTEXT_H
#endif // CLIENTCONTEXT_H

View File

@ -37,17 +37,14 @@ extern netif netif0;
class UdpContext
{
public:
typedef std::function<void(void)> rxhandler_t;
UdpContext(): _on_rx(nullptr), _refcnt(0)
UdpContext() : _on_rx(nullptr), _refcnt(0)
{
_sock = mockUDPSocket();
}
~UdpContext()
{
}
~UdpContext() { }
void ref()
{
@ -64,7 +61,7 @@ public:
bool connect(const ip_addr_t* addr, uint16_t port)
{
_dst = *addr;
_dst = *addr;
_dstport = port;
return true;
}
@ -103,7 +100,7 @@ public:
void setMulticastTTL(int ttl)
{
(void)ttl;
//mockverbose("TODO: UdpContext::setMulticastTTL\n");
// mockverbose("TODO: UdpContext::setMulticastTTL\n");
}
netif* getInputNetif() const
@ -156,13 +153,13 @@ public:
IPAddress getDestAddress()
{
mockverbose("TODO: implement UDP getDestAddress\n");
return 0; //ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
return 0; // ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
}
uint16_t getLocalPort()
{
mockverbose("TODO: implement UDP getLocalPort\n");
return 0; //
return 0; //
}
bool next()
@ -191,14 +188,14 @@ public:
int peek()
{
char c;
return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize) ? : -1;
return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize) ?: -1;
}
void flush()
{
//mockverbose("UdpContext::flush() does not follow arduino's flush concept\n");
//exit(EXIT_FAILURE);
// would be:
// mockverbose("UdpContext::flush() does not follow arduino's flush concept\n");
// exit(EXIT_FAILURE);
// would be:
_inbufsize = 0;
}
@ -206,7 +203,8 @@ public:
{
if (size + _outbufsize > sizeof _outbuf)
{
mockverbose("UdpContext::append: increase CCBUFSIZE (%d -> %zd)\n", CCBUFSIZE, (size + _outbufsize));
mockverbose("UdpContext::append: increase CCBUFSIZE (%d -> %zd)\n", CCBUFSIZE,
(size + _outbufsize));
exit(EXIT_FAILURE);
}
@ -217,9 +215,10 @@ public:
err_t trySend(ip_addr_t* addr = 0, uint16_t port = 0, bool keepBuffer = true)
{
uint32_t dst = addr ? addr->addr : _dst.addr;
uint16_t dstport = port ? : _dstport;
size_t wrt = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport);
uint32_t dst = addr ? addr->addr : _dst.addr;
uint16_t dstport = port ?: _dstport;
size_t wrt
= mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport);
err_t ret = _outbufsize ? ERR_OK : ERR_ABRT;
if (!keepBuffer || wrt == _outbufsize)
cancelBuffer();
@ -239,7 +238,7 @@ public:
bool sendTimeout(ip_addr_t* addr, uint16_t port,
esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
{
err_t err;
err_t err;
esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs);
while (((err = trySend(addr, port)) != ERR_OK) && !timeout)
delay(0);
@ -250,15 +249,14 @@ public:
void mock_cb(void)
{
if (_on_rx) _on_rx();
if (_on_rx)
_on_rx();
}
public:
static uint32_t staticMCastAddr;
private:
void translate_addr()
{
if (addrsize == 4)
@ -267,22 +265,22 @@ private:
memcpy(&ipv4, addr, 4);
ip4_addr_set_u32(&ip_2_ip4(_dst), ipv4);
// ^ this is a workaround for "type-punned pointer" with "*(uint32*)addr"
//ip4_addr_set_u32(&ip_2_ip4(_dst), *(uint32_t*)addr);
// ip4_addr_set_u32(&ip_2_ip4(_dst), *(uint32_t*)addr);
}
else
mockverbose("TODO unhandled udp address of size %d\n", (int)addrsize);
}
int _sock = -1;
int _sock = -1;
rxhandler_t _on_rx;
int _refcnt = 0;
int _refcnt = 0;
ip_addr_t _dst;
uint16_t _dstport;
uint16_t _dstport;
char _inbuf [CCBUFSIZE];
char _inbuf[CCBUFSIZE];
size_t _inbufsize = 0;
char _outbuf [CCBUFSIZE];
char _outbuf[CCBUFSIZE];
size_t _outbufsize = 0;
int _timeout_ms = 0;
@ -291,11 +289,11 @@ private:
uint8_t addr[16];
};
extern "C" inline err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
extern "C" inline err_t igmp_joingroup(const ip4_addr_t* ifaddr, const ip4_addr_t* groupaddr)
{
(void)ifaddr;
UdpContext::staticMCastAddr = groupaddr->addr;
return ERR_OK;
}
#endif//UDPCONTEXT_H
#endif // UDPCONTEXT_H

View File

@ -16,7 +16,6 @@
all copies or substantial portions of the Software.
*/
#include "littlefs_mock.h"
#include "spiffs_mock.h"
#include "spiffs/spiffs.h"
@ -56,7 +55,8 @@ LittleFSMock::LittleFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, con
void LittleFSMock::reset()
{
LittleFS = FS(FSImplPtr(new littlefs_impl::LittleFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
LittleFS = FS(
FSImplPtr(new littlefs_impl::LittleFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
load();
}
@ -72,47 +72,52 @@ LittleFSMock::~LittleFSMock()
LittleFS = FS(FSImplPtr(nullptr));
}
void LittleFSMock::load ()
void LittleFSMock::load()
{
if (!m_fs.size() || !m_storage.length())
return;
int fs = ::open(m_storage.c_str(), O_RDONLY);
if (fs == -1)
{
fprintf(stderr, "LittleFS: loading '%s': %s\n", m_storage.c_str(), strerror(errno));
return;
}
off_t flen = lseek(fs, 0, SEEK_END);
if (flen == (off_t)-1)
{
fprintf(stderr, "LittleFS: checking size of '%s': %s\n", m_storage.c_str(), strerror(errno));
fprintf(stderr, "LittleFS: checking size of '%s': %s\n", m_storage.c_str(),
strerror(errno));
return;
}
lseek(fs, 0, SEEK_SET);
if (flen != (off_t)m_fs.size())
{
fprintf(stderr, "LittleFS: size of '%s': %d does not match requested size %zd\n", m_storage.c_str(), (int)flen, m_fs.size());
fprintf(stderr, "LittleFS: size of '%s': %d does not match requested size %zd\n",
m_storage.c_str(), (int)flen, m_fs.size());
if (!m_overwrite && flen > 0)
{
fprintf(stderr, "LittleFS: aborting at user request\n");
exit(1);
}
fprintf(stderr, "LittleFS: continuing without loading at user request, '%s' will be overwritten\n", m_storage.c_str());
fprintf(stderr,
"LittleFS: continuing without loading at user request, '%s' will be overwritten\n",
m_storage.c_str());
}
else
{
fprintf(stderr, "LittleFS: loading %zi bytes from '%s'\n", m_fs.size(), m_storage.c_str());
ssize_t r = ::read(fs, m_fs.data(), m_fs.size());
if (r != (ssize_t)m_fs.size())
fprintf(stderr, "LittleFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r, strerror(errno));
fprintf(stderr, "LittleFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r,
strerror(errno));
}
::close(fs);
}
void LittleFSMock::save ()
void LittleFSMock::save()
{
if (!m_fs.size() || !m_storage.length())
return;

View File

@ -4,14 +4,14 @@
Based on spiffs_mock:
Copyright © 2016 Ivan Grokhotkov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
*/
@ -27,22 +27,25 @@
#define DEFAULT_LITTLEFS_FILE_NAME "littlefs.bin"
class LittleFSMock {
class LittleFSMock
{
public:
LittleFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString);
LittleFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page,
const String& storage = emptyString);
void reset();
~LittleFSMock();
protected:
void load ();
void save ();
void load();
void save();
std::vector<uint8_t> m_fs;
String m_storage;
bool m_overwrite;
String m_storage;
bool m_overwrite;
};
#define LITTLEFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) LittleFSMock littlefs_mock(size_kb * 1024, block_kb * 1024, page_b, storage)
#define LITTLEFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) \
LittleFSMock littlefs_mock(size_kb * 1024, block_kb * 1024, page_b, storage)
#define LITTLEFS_MOCK_RESET() littlefs_mock.reset()
#endif /* littlefs_mock_hpp */

View File

@ -1,18 +1,18 @@
/*
* Copyright (c) 2007, Cameron Rich
*
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@ -39,16 +39,15 @@
#define EXP_FUNC extern
#define STDCALL
#define MD5_SIZE 16
#define MD5_SIZE 16
typedef struct
typedef struct
{
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
uint8_t buffer[64]; /* input buffer */
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
uint8_t buffer[64]; /* input buffer */
} MD5_CTX;
/* Constants for MD5Transform routine.
*/
#define S11 7
@ -70,15 +69,13 @@ typedef struct
/* ----- static functions ----- */
static void MD5Transform(uint32_t state[4], const uint8_t block[64]);
static void Encode(uint8_t *output, uint32_t *input, uint32_t len);
static void Decode(uint32_t *output, const uint8_t *input, uint32_t len);
static void Encode(uint8_t* output, uint32_t* input, uint32_t len);
static void Decode(uint32_t* output, const uint8_t* input, uint32_t len);
static const uint8_t PADDING[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const uint8_t PADDING[64]
= { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* F, G, H and I are basic MD5 functions.
*/
@ -88,35 +85,39 @@ static const uint8_t PADDING[64] =
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation. */
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define FF(a, b, c, d, x, s, ac) \
{ \
(a) += F((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{ \
(a) += G((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{ \
(a) += H((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) \
{ \
(a) += I((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
/**
* MD5 initialization - begins an MD5 operation, writing a new ctx.
*/
EXP_FUNC void STDCALL MD5Init(MD5_CTX *ctx)
EXP_FUNC void STDCALL MD5Init(MD5_CTX* ctx)
{
ctx->count[0] = ctx->count[1] = 0;
@ -131,10 +132,10 @@ EXP_FUNC void STDCALL MD5Init(MD5_CTX *ctx)
/**
* Accepts an array of octets as the next portion of the message.
*/
EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
EXP_FUNC void STDCALL MD5Update(MD5_CTX* ctx, const uint8_t* msg, int len)
{
uint32_t x;
int i, partLen;
int i, partLen;
/* Compute number of bytes mod 64 */
x = (uint32_t)((ctx->count[0] >> 3) & 0x3F);
@ -147,7 +148,7 @@ EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
partLen = 64 - x;
/* Transform as many times as possible. */
if (len >= partLen)
if (len >= partLen)
{
memcpy(&ctx->buffer[x], msg, partLen);
MD5Transform(ctx->state, ctx->buffer);
@ -161,15 +162,15 @@ EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
i = 0;
/* Buffer remaining input */
memcpy(&ctx->buffer[x], &msg[i], len-i);
memcpy(&ctx->buffer[x], &msg[i], len - i);
}
/**
* Return the 128-bit message digest into the user's array
*/
EXP_FUNC void STDCALL MD5Final(uint8_t *digest, MD5_CTX *ctx)
EXP_FUNC void STDCALL MD5Final(uint8_t* digest, MD5_CTX* ctx)
{
uint8_t bits[8];
uint8_t bits[8];
uint32_t x, padLen;
/* Save number of bits */
@ -177,7 +178,7 @@ EXP_FUNC void STDCALL MD5Final(uint8_t *digest, MD5_CTX *ctx)
/* Pad out to 56 mod 64.
*/
x = (uint32_t)((ctx->count[0] >> 3) & 0x3f);
x = (uint32_t)((ctx->count[0] >> 3) & 0x3f);
padLen = (x < 56) ? (56 - x) : (120 - x);
MD5Update(ctx, PADDING, padLen);
@ -193,82 +194,81 @@ EXP_FUNC void STDCALL MD5Final(uint8_t *digest, MD5_CTX *ctx)
*/
static void MD5Transform(uint32_t state[4], const uint8_t block[64])
{
uint32_t a = state[0], b = state[1], c = state[2],
d = state[3], x[MD5_SIZE];
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[MD5_SIZE];
Decode(x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
@ -280,16 +280,16 @@ static void MD5Transform(uint32_t state[4], const uint8_t block[64])
* Encodes input (uint32_t) into output (uint8_t). Assumes len is
* a multiple of 4.
*/
static void Encode(uint8_t *output, uint32_t *input, uint32_t len)
static void Encode(uint8_t* output, uint32_t* input, uint32_t len)
{
uint32_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (uint8_t)(input[i] & 0xff);
output[j+1] = (uint8_t)((input[i] >> 8) & 0xff);
output[j+2] = (uint8_t)((input[i] >> 16) & 0xff);
output[j+3] = (uint8_t)((input[i] >> 24) & 0xff);
output[j] = (uint8_t)(input[i] & 0xff);
output[j + 1] = (uint8_t)((input[i] >> 8) & 0xff);
output[j + 2] = (uint8_t)((input[i] >> 16) & 0xff);
output[j + 3] = (uint8_t)((input[i] >> 24) & 0xff);
}
}
@ -297,11 +297,11 @@ static void Encode(uint8_t *output, uint32_t *input, uint32_t len)
* Decodes input (uint8_t) into output (uint32_t). Assumes len is
* a multiple of 4.
*/
static void Decode(uint32_t *output, const uint8_t *input, uint32_t len)
static void Decode(uint32_t* output, const uint8_t* input, uint32_t len)
{
uint32_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j + 1]) << 8)
| (((uint32_t)input[j + 2]) << 16) | (((uint32_t)input[j + 3]) << 24);
}

View File

@ -30,7 +30,8 @@
*/
#define CORE_MOCK 1
#define MOCK "(mock) " // TODO: provide common logging API instead of adding this string everywhere?
#define MOCK \
"(mock) " // TODO: provide common logging API instead of adding this string everywhere?
//
@ -57,15 +58,15 @@
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
// TODO: #include <stdlib_noniso.h> ?
char* itoa (int val, char *s, int radix);
char* ltoa (long val, char *s, int radix);
// TODO: #include <stdlib_noniso.h> ?
char* itoa(int val, char* s, int radix);
char* ltoa(long val, char* s, int radix);
size_t strlcat(char *dst, const char *src, size_t size);
size_t strlcpy(char *dst, const char *src, size_t size);
size_t strlcat(char* dst, const char* src, size_t size);
size_t strlcpy(char* dst, const char* src, size_t size);
#ifdef __cplusplus
}
@ -74,7 +75,7 @@ size_t strlcpy(char *dst, const char *src, size_t size);
// exotic typedefs used in the sdk
#include <stdint.h>
typedef uint8_t uint8;
typedef uint8_t uint8;
typedef uint32_t uint32;
//
@ -97,26 +98,30 @@ uint32_t esp_get_cycle_count();
//
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include <osapi.h>
int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
int ets_printf(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
#define os_printf_plus printf
#define ets_vsnprintf vsnprintf
inline void ets_putc (char c) { putchar(c); }
inline void ets_putc(char c)
{
putchar(c);
}
int mockverbose (const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
int mockverbose(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
extern const char* host_interface; // cmdline parameter
extern bool serial_timestamp;
extern int mock_port_shifter;
extern bool blocking_uart;
extern uint32_t global_source_address; // 0 = INADDR_ANY by default
extern const char* host_interface; // cmdline parameter
extern bool serial_timestamp;
extern int mock_port_shifter;
extern bool blocking_uart;
extern uint32_t global_source_address; // 0 = INADDR_ANY by default
#define NO_GLOBAL_BINDING 0xffffffff
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to
void loop_end();
void loop_end();
#ifdef __cplusplus
}
@ -132,41 +137,48 @@ void loop_end();
// uart
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
void uart_new_data(const int uart_nr, uint8_t data);
void uart_new_data(const int uart_nr, uint8_t data);
#ifdef __cplusplus
}
#endif
// tcp
int mockSockSetup (int sock);
int mockConnect (uint32_t addr, int& sock, int port);
ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize);
ssize_t mockPeekBytes (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
ssize_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms);
int serverAccept (int sock);
int mockSockSetup(int sock);
int mockConnect(uint32_t addr, int& sock, int port);
ssize_t mockFillInBuf(int sock, char* ccinbuf, size_t& ccinbufsize);
ssize_t mockPeekBytes(int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
ssize_t mockRead(int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize);
ssize_t mockWrite(int sock, const uint8_t* data, size_t size, int timeout_ms);
int serverAccept(int sock);
// udp
void check_incoming_udp ();
int mockUDPSocket ();
bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast = 0);
size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port);
size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize);
size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize);
size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port);
void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize);
void check_incoming_udp();
int mockUDPSocket();
bool mockUDPListen(int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast = 0);
size_t mockUDPFillInBuf(int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize,
uint8_t addr[16], uint16_t& port);
size_t mockUDPPeekBytes(int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf,
size_t& ccinbufsize);
size_t mockUDPRead(int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf,
size_t& ccinbufsize);
size_t mockUDPWrite(int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4,
uint16_t port);
void mockUDPSwallow(size_t copied, char* ccinbuf, size_t& ccinbufsize);
class UdpContext;
void register_udp (int sock, UdpContext* udp = nullptr);
void register_udp(int sock, UdpContext* udp = nullptr);
//
void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb = 8, size_t page_b = 512);
void mock_stop_spiffs ();
void mock_start_littlefs (const String& fname, size_t size_kb, size_t block_kb = 8, size_t page_b = 512);
void mock_stop_littlefs ();
void mock_start_spiffs(const String& fname, size_t size_kb, size_t block_kb = 8,
size_t page_b = 512);
void mock_stop_spiffs();
void mock_start_littlefs(const String& fname, size_t size_kb, size_t block_kb = 8,
size_t page_b = 512);
void mock_stop_littlefs();
//
@ -174,4 +186,4 @@ void mock_stop_littlefs ();
//
#endif // __cplusplus
#endif // __cplusplus

View File

@ -1,19 +1,18 @@
/*
noniso.cpp - replacements for non-ISO functions used by Arduino core
Copyright © 2016 Ivan Grokhotkov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
*/
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
@ -21,61 +20,69 @@
#include <math.h>
#include "stdlib_noniso.h"
void reverse(char* begin, char* end) {
char *is = begin;
char *ie = end - 1;
while(is < ie) {
void reverse(char* begin, char* end)
{
char* is = begin;
char* ie = end - 1;
while (is < ie)
{
char tmp = *ie;
*ie = *is;
*is = tmp;
*ie = *is;
*is = tmp;
++is;
--ie;
}
}
char* utoa(unsigned value, char* result, int base) {
if(base < 2 || base > 16) {
char* utoa(unsigned value, char* result, int base)
{
if (base < 2 || base > 16)
{
*result = 0;
return result;
}
char* out = result;
char* out = result;
unsigned quotient = value;
do {
do
{
const unsigned tmp = quotient / base;
*out = "0123456789abcdef"[quotient - (tmp * base)];
*out = "0123456789abcdef"[quotient - (tmp * base)];
++out;
quotient = tmp;
} while(quotient);
} while (quotient);
reverse(result, out);
*out = 0;
return result;
}
char* itoa(int value, char* result, int base) {
if(base < 2 || base > 16) {
char* itoa(int value, char* result, int base)
{
if (base < 2 || base > 16)
{
*result = 0;
return result;
}
if (base != 10) {
return utoa((unsigned)value, result, base);
}
if (base != 10)
{
return utoa((unsigned)value, result, base);
}
char* out = result;
int quotient = abs(value);
char* out = result;
int quotient = abs(value);
do {
do
{
const int tmp = quotient / base;
*out = "0123456789abcdef"[quotient - (tmp * base)];
*out = "0123456789abcdef"[quotient - (tmp * base)];
++out;
quotient = tmp;
} while(quotient);
} while (quotient);
// Apply negative sign
if(value < 0)
if (value < 0)
*out++ = '-';
reverse(result, out);
@ -83,17 +90,19 @@ char* itoa(int value, char* result, int base) {
return result;
}
int atoi(const char* s) {
return (int) atol(s);
int atoi(const char* s)
{
return (int)atol(s);
}
long atol(const char* s) {
char * tmp;
long atol(const char* s)
{
char* tmp;
return strtol(s, &tmp, 10);
}
double atof(const char* s) {
char * tmp;
double atof(const char* s)
{
char* tmp;
return strtod(s, &tmp);
}

View File

@ -1,19 +1,18 @@
/*
pins_arduino.h
Copyright © 2016 Ivan Grokhotkov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
*/
#ifndef pins_arduino_h
#define pins_arduino_h
#endif /* pins_arduino_h */

View File

@ -35,9 +35,9 @@
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
#include <machine/ansi.h> /* for __offsetof */
#include <machine/ansi.h> /* for __offsetof */
/*
* This file defines four types of data structures: singly-linked lists,
@ -106,322 +106,373 @@
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD(name, type) \
struct name \
{ \
struct type* slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ \
NULL \
}
#define SLIST_ENTRY(type) \
struct \
{ \
struct type* sle_next; /* next element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); (var); (var) = SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INIT(head) \
do \
{ \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) \
do \
{ \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) \
do \
{ \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = \
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
} \
} while (0)
#define SLIST_REMOVE(head, elm, type, field) \
do \
{ \
if (SLIST_FIRST((head)) == (elm)) \
{ \
SLIST_REMOVE_HEAD((head), field); \
} \
else \
{ \
struct type* curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
} \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) \
do \
{ \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_HEAD(name, type) \
struct name \
{ \
struct type* stqh_first; /* first element */ \
struct type** stqh_last; /* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_HEAD_INITIALIZER(head) \
{ \
NULL, &(head).stqh_first \
}
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
#define STAILQ_ENTRY(type) \
struct \
{ \
struct type* stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_CONCAT(head1, head2) \
do \
{ \
if (!STAILQ_EMPTY((head2))) \
{ \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH(var, head, field) \
for ((var) = STAILQ_FIRST((head)); (var); (var) = STAILQ_NEXT((var), field))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INIT(head) \
do \
{ \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) \
do \
{ \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) \
do \
{ \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) \
do \
{ \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \
NULL : \
((struct type *) \
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) \
? NULL \
: ((struct type*)((char*)((head)->stqh_last) - __offsetof(struct type, field))))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
if ((STAILQ_NEXT(curelm, field) = \
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
} \
} while (0)
#define STAILQ_REMOVE(head, elm, type, field) \
do \
{ \
if (STAILQ_FIRST((head)) == (elm)) \
{ \
STAILQ_REMOVE_HEAD((head), field); \
} \
else \
{ \
struct type* curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
if ((STAILQ_NEXT(curelm, field) = STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) \
== NULL) \
(head)->stqh_last = &STAILQ_NEXT((curelm), field); \
} \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) \
do \
{ \
if ((STAILQ_FIRST((head)) = STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) \
do \
{ \
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD(name, type) \
struct name \
{ \
struct type* lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_HEAD_INITIALIZER(head) \
{ \
NULL \
}
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
#define LIST_ENTRY(type) \
struct \
{ \
struct type* le_next; /* next element */ \
struct type** le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); (var); (var) = LIST_NEXT((var), field))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INIT(head) \
do \
{ \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) \
do \
{ \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL) \
LIST_NEXT((listelm), field)->field.le_prev = &LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) \
do \
{ \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) \
do \
{ \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_REMOVE(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0)
#define LIST_REMOVE(elm, field) \
do \
{ \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = (elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0)
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD(name, type) \
struct name \
{ \
struct type* tqh_first; /* first element */ \
struct type** tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_HEAD_INITIALIZER(head) \
{ \
NULL, &(head).tqh_first \
}
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
#define TAILQ_ENTRY(type) \
struct \
{ \
struct type* tqe_next; /* next element */ \
struct type** tqe_prev; /* address of previous next element */ \
}
/*
* Tail queue functions.
*/
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
} while (0)
#define TAILQ_CONCAT(head1, head2, field) \
do \
{ \
if (!TAILQ_EMPTY(head2)) \
{ \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
} while (0)
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); (var); (var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); (var); (var) = TAILQ_PREV((var), headname, field))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INIT(head) \
do \
{ \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) \
do \
{ \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) \
do \
{ \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) \
do \
{ \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = &TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) \
do \
{ \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_LAST(head, headname) (*(((struct headname*)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_PREV(elm, headname, field) (*(((struct headname*)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) \
do \
{ \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = (elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
} while (0)
#ifdef _KERNEL
@ -430,39 +481,37 @@ struct { \
* They bogusly assumes that all queue heads look alike.
*/
struct quehead {
struct quehead *qh_link;
struct quehead *qh_rlink;
struct quehead
{
struct quehead* qh_link;
struct quehead* qh_rlink;
};
#ifdef __GNUC__
#ifdef __GNUC__
static __inline void
insque(void *a, void *b)
static __inline void insque(void* a, void* b)
{
struct quehead *element = (struct quehead *)a,
*head = (struct quehead *)b;
struct quehead *element = (struct quehead*)a, *head = (struct quehead*)b;
element->qh_link = head->qh_link;
element->qh_rlink = head;
head->qh_link = element;
element->qh_link->qh_rlink = element;
element->qh_link = head->qh_link;
element->qh_rlink = head;
head->qh_link = element;
element->qh_link->qh_rlink = element;
}
static __inline void
remque(void *a)
static __inline void remque(void* a)
{
struct quehead *element = (struct quehead *)a;
struct quehead* element = (struct quehead*)a;
element->qh_link->qh_rlink = element->qh_rlink;
element->qh_rlink->qh_link = element->qh_link;
element->qh_rlink = 0;
element->qh_link->qh_rlink = element->qh_rlink;
element->qh_rlink->qh_link = element->qh_link;
element->qh_rlink = 0;
}
#else /* !__GNUC__ */
void insque(void *a, void *b);
void remque(void *a);
void insque(void* a, void* b);
void remque(void* a);
#endif /* __GNUC__ */

View File

@ -18,4 +18,4 @@
#define SDSIZE 16LL
uint64_t _sdCardSizeB = 0;
uint8_t *_sdCard = nullptr;
uint8_t* _sdCard = nullptr;

View File

@ -21,22 +21,32 @@
#include <vector>
#include <FS.h>
class SDFSMock {
class SDFSMock
{
public:
SDFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString) { (void)fs_size; (void)fs_block; (void)fs_page; (void)storage; }
SDFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString)
{
(void)fs_size;
(void)fs_block;
(void)fs_page;
(void)storage;
}
void reset() { }
~SDFSMock() { }
};
extern uint64_t _sdCardSizeB;
extern uint8_t *_sdCard;
extern uint8_t* _sdCard;
#define SDFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) \
SDFS.end(); \
SDFSMock sdfs_mock(size_kb * 1024, block_kb * 1024, page_b, storage); free(_sdCard); \
_sdCardSizeB = size_kb ? 16 * 1024 * 1024 : 0; \
if (_sdCardSizeB) _sdCard = (uint8_t*)calloc(_sdCardSizeB, 1); \
else _sdCard = nullptr; \
#define SDFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) \
SDFS.end(); \
SDFSMock sdfs_mock(size_kb * 1024, block_kb * 1024, page_b, storage); \
free(_sdCard); \
_sdCardSizeB = size_kb ? 16 * 1024 * 1024 : 0; \
if (_sdCardSizeB) \
_sdCard = (uint8_t*)calloc(_sdCardSizeB, 1); \
else \
_sdCard = nullptr; \
SDFS.setConfig(SDFSConfig().setAutoFormat(true));
#define SDFS_MOCK_RESET() sdfs_mock.reset()

View File

@ -13,7 +13,6 @@
all copies or substantial portions of the Software.
*/
#include "spiffs_mock.h"
#include "spiffs/spiffs.h"
#include "debug.h"
@ -54,7 +53,8 @@ SpiffsMock::SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const S
void SpiffsMock::reset()
{
SPIFFS = FS(FSImplPtr(new spiffs_impl::SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
SPIFFS
= FS(FSImplPtr(new spiffs_impl::SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
load();
}
@ -70,18 +70,18 @@ SpiffsMock::~SpiffsMock()
SPIFFS = FS(FSImplPtr(nullptr));
}
void SpiffsMock::load ()
void SpiffsMock::load()
{
if (!m_fs.size() || !m_storage.length())
return;
int fs = ::open(m_storage.c_str(), O_RDONLY);
if (fs == -1)
{
fprintf(stderr, "SPIFFS: loading '%s': %s\n", m_storage.c_str(), strerror(errno));
return;
}
off_t flen = lseek(fs, 0, SEEK_END);
if (flen == (off_t)-1)
{
@ -89,28 +89,32 @@ void SpiffsMock::load ()
return;
}
lseek(fs, 0, SEEK_SET);
if (flen != (off_t)m_fs.size())
{
fprintf(stderr, "SPIFFS: size of '%s': %d does not match requested size %zd\n", m_storage.c_str(), (int)flen, m_fs.size());
fprintf(stderr, "SPIFFS: size of '%s': %d does not match requested size %zd\n",
m_storage.c_str(), (int)flen, m_fs.size());
if (!m_overwrite && flen > 0)
{
fprintf(stderr, "SPIFFS: aborting at user request\n");
exit(1);
}
fprintf(stderr, "SPIFFS: continuing without loading at user request, '%s' will be overwritten\n", m_storage.c_str());
fprintf(stderr,
"SPIFFS: continuing without loading at user request, '%s' will be overwritten\n",
m_storage.c_str());
}
else
{
fprintf(stderr, "SPIFFS: loading %zi bytes from '%s'\n", m_fs.size(), m_storage.c_str());
ssize_t r = ::read(fs, m_fs.data(), m_fs.size());
if (r != (ssize_t)m_fs.size())
fprintf(stderr, "SPIFFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r, strerror(errno));
fprintf(stderr, "SPIFFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r,
strerror(errno));
}
::close(fs);
}
void SpiffsMock::save ()
void SpiffsMock::save()
{
if (!m_fs.size() || !m_storage.length())
return;
@ -130,4 +134,3 @@ void SpiffsMock::save ()
}
#pragma GCC diagnostic pop

View File

@ -1,14 +1,14 @@
/*
spiffs_mock.h - SPIFFS HAL mock for host side testing
Copyright © 2016 Ivan Grokhotkov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
*/
@ -24,22 +24,25 @@
#define DEFAULT_SPIFFS_FILE_NAME "spiffs.bin"
class SpiffsMock {
class SpiffsMock
{
public:
SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString);
SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page,
const String& storage = emptyString);
void reset();
~SpiffsMock();
protected:
void load ();
void save ();
void load();
void save();
std::vector<uint8_t> m_fs;
String m_storage;
bool m_overwrite;
String m_storage;
bool m_overwrite;
};
#define SPIFFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) SpiffsMock spiffs_mock(size_kb * 1024, block_kb * 1024, page_b, storage)
#define SPIFFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) \
SpiffsMock spiffs_mock(size_kb * 1024, block_kb * 1024, page_b, storage)
#define SPIFFS_MOCK_RESET() spiffs_mock.reset()
#endif /* spiffs_mock_hpp */

View File

@ -5,25 +5,24 @@
'_cups_strlcat()' - Safely concatenate two strings.
*/
size_t /* O - Length of string */
strlcat(char *dst, /* O - Destination string */
const char *src, /* I - Source string */
size_t size) /* I - Size of destination string buffer */
size_t /* O - Length of string */
strlcat(char* dst, /* O - Destination string */
const char* src, /* I - Source string */
size_t size) /* I - Size of destination string buffer */
{
size_t srclen; /* Length of source string */
size_t dstlen; /* Length of destination string */
size_t srclen; /* Length of source string */
size_t dstlen; /* Length of destination string */
/*
Figure out how much room is left...
*/
dstlen = strlen(dst);
size -= dstlen + 1;
size -= dstlen + 1;
if (!size)
{
return (dstlen); /* No room, return immediately... */
return (dstlen); /* No room, return immediately... */
}
/*
@ -53,19 +52,18 @@ strlcat(char *dst, /* O - Destination string */
'_cups_strlcpy()' - Safely copy two strings.
*/
size_t /* O - Length of string */
strlcpy(char *dst, /* O - Destination string */
const char *src, /* I - Source string */
size_t /* O - Length of string */
strlcpy(char* dst, /* O - Destination string */
const char* src, /* I - Source string */
size_t size) /* I - Size of destination string buffer */
{
size_t srclen; /* Length of source string */
size_t srclen; /* Length of source string */
/*
Figure out how much room is needed...
*/
size --;
size--;
srclen = strlen(src);

View File

@ -43,7 +43,7 @@
#include <LwipDhcpServer.h>
bool DhcpServer::set_dhcps_lease(struct dhcps_lease *please)
bool DhcpServer::set_dhcps_lease(struct dhcps_lease* please)
{
(void)please;
return false;
@ -62,22 +62,20 @@ bool DhcpServer::set_dhcps_offer_option(uint8 level, void* optarg)
return false;
}
void DhcpServer::end ()
{
}
void DhcpServer::end() { }
bool DhcpServer::begin (struct ip_info *info)
bool DhcpServer::begin(struct ip_info* info)
{
(void)info;
return false;
}
DhcpServer::DhcpServer (netif* netif)
DhcpServer::DhcpServer(netif* netif)
{
(void)netif;
}
DhcpServer::~DhcpServer ()
DhcpServer::~DhcpServer()
{
end();
}
@ -86,7 +84,6 @@ DhcpServer dhcpSoftAP(nullptr);
extern "C"
{
#include <user_interface.h>
#include <lwip/netif.h>
@ -120,14 +117,14 @@ extern "C"
return 1;
}
bool wifi_station_get_config(struct station_config *config)
bool wifi_station_get_config(struct station_config* config)
{
strcpy((char*)config->ssid, "emulated-ssid");
strcpy((char*)config->password, "emulated-ssid-password");
config->bssid_set = 0;
for (int i = 0; i < 6; i++)
config->bssid[i] = i;
config->threshold.rssi = 1;
config->threshold.rssi = 1;
config->threshold.authmode = AUTH_WPA_PSK;
#ifdef NONOSDK3V0
config->open_and_wep_mode_disable = true;
@ -135,9 +132,7 @@ extern "C"
return true;
}
void wifi_fpm_close(void)
{
}
void wifi_fpm_close(void) { }
sint8 wifi_fpm_do_sleep(uint32 sleep_time_in_us)
{
@ -145,34 +140,30 @@ extern "C"
return 1;
}
void wifi_fpm_do_wakeup(void)
{
}
void wifi_fpm_do_wakeup(void) { }
void wifi_fpm_open(void)
{
}
void wifi_fpm_open(void) { }
void wifi_fpm_set_sleep_type(sleep_type_t type)
{
(void)type;
}
uint32_t global_ipv4_netfmt = 0; // global binding
uint32_t global_ipv4_netfmt = 0; // global binding
netif netif0;
netif netif0;
uint32_t global_source_address = INADDR_ANY;
bool wifi_get_ip_info(uint8 if_index, struct ip_info *info)
bool wifi_get_ip_info(uint8 if_index, struct ip_info* info)
{
// emulate wifi_get_ip_info()
// ignore if_index
// use global option -i (host_interface) to select bound interface/address
struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL;
uint32_t ipv4 = lwip_htonl(0x7f000001);
uint32_t mask = lwip_htonl(0xff000000);
global_source_address = INADDR_ANY; // =0
struct ifaddrs *ifAddrStruct = NULL, *ifa = NULL;
uint32_t ipv4 = lwip_htonl(0x7f000001);
uint32_t mask = lwip_htonl(0xff000000);
global_source_address = INADDR_ANY; // =0
if (getifaddrs(&ifAddrStruct) != 0)
{
@ -186,22 +177,24 @@ extern "C"
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
{
mockverbose("host: interface: %s", ifa->ifa_name);
if (ifa->ifa_addr
&& ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only
)
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only
)
{
auto test_ipv4 = lwip_ntohl(*(uint32_t*) & ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr);
auto test_ipv4
= lwip_ntohl(*(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr);
mockverbose(" IPV4 (0x%08lx)", test_ipv4);
if ((test_ipv4 & 0xff000000) == 0x7f000000)
// 127./8
mockverbose(" (local, ignored)");
else
{
if (!host_interface || (host_interface && strcmp(ifa->ifa_name, host_interface) == 0))
if (!host_interface
|| (host_interface && strcmp(ifa->ifa_name, host_interface) == 0))
{
// use the first non-local interface, or, if specified, the one selected by user on cmdline
ipv4 = *(uint32_t*) & ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
mask = *(uint32_t*) & ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
// use the first non-local interface, or, if specified, the one selected by
// user on cmdline
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
mockverbose(" (selected)\n");
if (host_interface)
global_source_address = ntohl(ipv4);
@ -216,7 +209,7 @@ extern "C"
freeifaddrs(ifAddrStruct);
(void)if_index;
//if (if_index != STATION_IF)
// if (if_index != STATION_IF)
// fprintf(stderr, "we are not AP");
if (global_ipv4_netfmt == NO_GLOBAL_BINDING)
@ -224,15 +217,15 @@ extern "C"
if (info)
{
info->ip.addr = ipv4;
info->ip.addr = ipv4;
info->netmask.addr = mask;
info->gw.addr = ipv4;
info->gw.addr = ipv4;
netif0.ip_addr.addr = ipv4;
netif0.netmask.addr = mask;
netif0.gw.addr = ipv4;
netif0.flags = NETIF_FLAG_IGMP | NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
netif0.next = nullptr;
netif0.gw.addr = ipv4;
netif0.flags = NETIF_FLAG_IGMP | NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
netif0.next = nullptr;
}
return true;
@ -243,7 +236,7 @@ extern "C"
return 1;
}
bool wifi_get_macaddr(uint8 if_index, uint8 *macaddr)
bool wifi_get_macaddr(uint8 if_index, uint8* macaddr)
{
(void)if_index;
macaddr[0] = 0xde;
@ -267,7 +260,7 @@ extern "C"
return MIN_SLEEP_T;
}
#endif // nonos-sdk-pre-3
#endif // nonos-sdk-pre-3
sleep_type_t wifi_get_sleep_type(void)
{
@ -281,13 +274,13 @@ extern "C"
}
wifi_event_handler_cb_t wifi_event_handler_cb_emu = nullptr;
void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb)
void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb)
{
wifi_event_handler_cb_emu = cb;
mockverbose("TODO: wifi_set_event_handler_cb set\n");
}
bool wifi_set_ip_info(uint8 if_index, struct ip_info *info)
bool wifi_set_ip_info(uint8 if_index, struct ip_info* info)
{
(void)if_index;
(void)info;
@ -352,12 +345,12 @@ extern "C"
return true;
}
bool wifi_station_get_config_default(struct station_config *config)
bool wifi_station_get_config_default(struct station_config* config)
{
return wifi_station_get_config(config);
}
char wifi_station_get_hostname_str [128];
char wifi_station_get_hostname_str[128];
const char* wifi_station_get_hostname(void)
{
return strcpy(wifi_station_get_hostname_str, "esposix");
@ -378,19 +371,19 @@ extern "C"
return set != 0;
}
bool wifi_station_set_config(struct station_config *config)
bool wifi_station_set_config(struct station_config* config)
{
(void)config;
return true;
}
bool wifi_station_set_config_current(struct station_config *config)
bool wifi_station_set_config_current(struct station_config* config)
{
(void)config;
return true;
}
bool wifi_station_set_hostname(const char *name)
bool wifi_station_set_hostname(const char* name)
{
(void)name;
return true;
@ -422,20 +415,20 @@ extern "C"
return true;
}
bool wifi_softap_get_config(struct softap_config *config)
bool wifi_softap_get_config(struct softap_config* config)
{
strcpy((char*)config->ssid, "apssid");
strcpy((char*)config->password, "appasswd");
config->ssid_len = strlen("appasswd");
config->channel = 1;
config->authmode = AUTH_WPA2_PSK;
config->ssid_hidden = 0;
config->max_connection = 4;
config->ssid_len = strlen("appasswd");
config->channel = 1;
config->authmode = AUTH_WPA2_PSK;
config->ssid_hidden = 0;
config->max_connection = 4;
config->beacon_interval = 100;
return true;
}
bool wifi_softap_get_config_default(struct softap_config *config)
bool wifi_softap_get_config_default(struct softap_config* config)
{
return wifi_softap_get_config(config);
}
@ -445,19 +438,19 @@ extern "C"
return 2;
}
bool wifi_softap_set_config(struct softap_config *config)
bool wifi_softap_set_config(struct softap_config* config)
{
(void)config;
return true;
}
bool wifi_softap_set_config_current(struct softap_config *config)
bool wifi_softap_set_config_current(struct softap_config* config)
{
(void)config;
return true;
}
bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
bool wifi_softap_set_dhcps_lease(struct dhcps_lease* please)
{
(void)please;
return true;
@ -476,7 +469,7 @@ extern "C"
return true;
}
bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb)
bool wifi_station_scan(struct scan_config* config, scan_done_cb_t cb)
{
(void)config;
cb(nullptr, FAIL);
@ -498,7 +491,7 @@ extern "C"
(void)intr;
}
void dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
void dns_setserver(u8_t numdns, ip_addr_t* dnsserver)
{
(void)numdns;
(void)dnsserver;
@ -511,11 +504,10 @@ extern "C"
return addr;
}
#include <smartconfig.h>
bool smartconfig_start(sc_callback_t cb, ...)
{
//XXXFIXME ... -> ptr
// XXXFIXME ... -> ptr
cb(SC_STATUS_LINK, NULL);
return true;
}
@ -530,4 +522,4 @@ extern "C"
return NONE_SLEEP_T;
}
} // extern "C"
} // extern "C"

View File

@ -2,245 +2,239 @@
#include "PolledTimeout.h"
#define mockverbose printf
#include "common/MockEsp.cpp" // getCycleCount
#include "common/MockEsp.cpp" // getCycleCount
//This won't work for
// This won't work for
template<typename argT>
inline bool
fuzzycomp(argT a, argT b)
inline bool fuzzycomp(argT a, argT b)
{
const argT epsilon = 10;
return (std::max(a,b) - std::min(a,b) <= epsilon);
const argT epsilon = 10;
return (std::max(a, b) - std::min(a, b) <= epsilon);
}
TEST_CASE("OneShot Timeout 500000000ns (0.5s)", "[polledTimeout]")
{
using esp8266::polledTimeout::oneShotFastNs;
using timeType = oneShotFastNs::timeType;
timeType before, after, delta;
using esp8266::polledTimeout::oneShotFastNs;
using timeType = oneShotFastNs::timeType;
timeType before, after, delta;
Serial.println("OneShot Timeout 500000000ns (0.5s)");
Serial.println("OneShot Timeout 500000000ns (0.5s)");
oneShotFastNs timeout(500000000);
before = micros();
while(!timeout.expired())
yield();
after = micros();
oneShotFastNs timeout(500000000);
before = micros();
while (!timeout.expired())
yield();
after = micros();
delta = after - before;
Serial.printf("delta = %u\n", delta);
delta = after - before;
Serial.printf("delta = %u\n", delta);
REQUIRE(fuzzycomp(delta/1000, (timeType)500));
REQUIRE(fuzzycomp(delta / 1000, (timeType)500));
Serial.print("reset\n");
Serial.print("reset\n");
timeout.reset();
before = micros();
while (!timeout)
yield();
after = micros();
timeout.reset();
before = micros();
while(!timeout)
yield();
after = micros();
delta = after - before;
Serial.printf("delta = %u\n", delta);
delta = after - before;
Serial.printf("delta = %u\n", delta);
REQUIRE(fuzzycomp(delta/1000, (timeType)500));
REQUIRE(fuzzycomp(delta / 1000, (timeType)500));
}
TEST_CASE("OneShot Timeout 3000000us", "[polledTimeout]")
{
using esp8266::polledTimeout::oneShotFastUs;
using timeType = oneShotFastUs::timeType;
timeType before, after, delta;
using esp8266::polledTimeout::oneShotFastUs;
using timeType = oneShotFastUs::timeType;
timeType before, after, delta;
Serial.println("OneShot Timeout 3000000us");
Serial.println("OneShot Timeout 3000000us");
oneShotFastUs timeout(3000000);
before = micros();
while(!timeout.expired())
yield();
after = micros();
oneShotFastUs timeout(3000000);
before = micros();
while (!timeout.expired())
yield();
after = micros();
delta = after - before;
Serial.printf("delta = %u\n", delta);
delta = after - before;
Serial.printf("delta = %u\n", delta);
REQUIRE(fuzzycomp(delta/1000, (timeType)3000));
REQUIRE(fuzzycomp(delta / 1000, (timeType)3000));
Serial.print("reset\n");
Serial.print("reset\n");
timeout.reset();
before = micros();
while (!timeout)
yield();
after = micros();
timeout.reset();
before = micros();
while(!timeout)
yield();
after = micros();
delta = after - before;
Serial.printf("delta = %u\n", delta);
delta = after - before;
Serial.printf("delta = %u\n", delta);
REQUIRE(fuzzycomp(delta/1000, (timeType)3000));
REQUIRE(fuzzycomp(delta / 1000, (timeType)3000));
}
TEST_CASE("OneShot Timeout 3000ms", "[polledTimeout]")
{
using esp8266::polledTimeout::oneShotMs;
using timeType = oneShotMs::timeType;
timeType before, after, delta;
using esp8266::polledTimeout::oneShotMs;
using timeType = oneShotMs::timeType;
timeType before, after, delta;
Serial.println("OneShot Timeout 3000ms");
Serial.println("OneShot Timeout 3000ms");
oneShotMs timeout(3000);
before = millis();
while(!timeout.expired())
yield();
after = millis();
oneShotMs timeout(3000);
before = millis();
while (!timeout.expired())
yield();
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)3000));
REQUIRE(fuzzycomp(delta, (timeType)3000));
Serial.print("reset\n");
Serial.print("reset\n");
timeout.reset();
before = millis();
while (!timeout)
yield();
after = millis();
timeout.reset();
before = millis();
while(!timeout)
yield();
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)3000));
REQUIRE(fuzzycomp(delta, (timeType)3000));
}
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms", "[polledTimeout]")
{
using esp8266::polledTimeout::oneShotMs;
using timeType = oneShotMs::timeType;
timeType before, after, delta;
using esp8266::polledTimeout::oneShotMs;
using timeType = oneShotMs::timeType;
timeType before, after, delta;
Serial.println("OneShot Timeout 3000ms");
Serial.println("OneShot Timeout 3000ms");
oneShotMs timeout(3000);
before = millis();
while(!timeout.expired())
yield();
after = millis();
oneShotMs timeout(3000);
before = millis();
while (!timeout.expired())
yield();
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)3000));
REQUIRE(fuzzycomp(delta, (timeType)3000));
Serial.print("reset\n");
Serial.print("reset\n");
timeout.reset(1000);
before = millis();
while (!timeout)
yield();
after = millis();
timeout.reset(1000);
before = millis();
while(!timeout)
yield();
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)1000));
REQUIRE(fuzzycomp(delta, (timeType)1000));
}
TEST_CASE("Periodic Timeout 1T 3000ms", "[polledTimeout]")
{
using esp8266::polledTimeout::periodicMs;
using timeType = periodicMs::timeType;
timeType before, after, delta;
using esp8266::polledTimeout::periodicMs;
using timeType = periodicMs::timeType;
timeType before, after, delta;
Serial.println("Periodic Timeout 1T 3000ms");
Serial.println("Periodic Timeout 1T 3000ms");
periodicMs timeout(3000);
before = millis();
while(!timeout)
yield();
after = millis();
periodicMs timeout(3000);
before = millis();
while (!timeout)
yield();
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)3000));
REQUIRE(fuzzycomp(delta, (timeType)3000));
Serial.print("no reset needed\n");
Serial.print("no reset needed\n");
before = millis();
while(!timeout)
yield();
after = millis();
before = millis();
while (!timeout)
yield();
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)3000));
REQUIRE(fuzzycomp(delta, (timeType)3000));
}
TEST_CASE("Periodic Timeout 10T 1000ms", "[polledTimeout]")
{
using esp8266::polledTimeout::periodicMs;
using timeType = periodicMs::timeType;
timeType before, after, delta;
using esp8266::polledTimeout::periodicMs;
using timeType = periodicMs::timeType;
timeType before, after, delta;
Serial.println("Periodic 10T Timeout 1000ms");
Serial.println("Periodic 10T Timeout 1000ms");
int counter = 10;
int counter = 10;
periodicMs timeout(1000);
before = millis();
while(1)
{
if(timeout)
periodicMs timeout(1000);
before = millis();
while (1)
{
Serial.print("*");
if(!--counter)
break;
yield();
if (timeout)
{
Serial.print("*");
if (!--counter)
break;
yield();
}
}
}
after = millis();
after = millis();
delta = after - before;
Serial.printf("\ndelta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)10000));
delta = after - before;
Serial.printf("\ndelta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)10000));
}
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms custom yield", "[polledTimeout]")
{
using YieldOrSkipPolicy = esp8266::polledTimeout::YieldPolicy::YieldOrSkip;
using oneShotMsYield = esp8266::polledTimeout::timeoutTemplate<false, YieldOrSkipPolicy>;
using timeType = oneShotMsYield::timeType;
timeType before, after, delta;
using YieldOrSkipPolicy = esp8266::polledTimeout::YieldPolicy::YieldOrSkip;
using oneShotMsYield = esp8266::polledTimeout::timeoutTemplate<false, YieldOrSkipPolicy>;
using timeType = oneShotMsYield::timeType;
timeType before, after, delta;
Serial.println("OneShot Timeout 3000ms");
Serial.println("OneShot Timeout 3000ms");
oneShotMsYield timeout(3000);
before = millis();
while (!timeout.expired())
;
after = millis();
oneShotMsYield timeout(3000);
before = millis();
while(!timeout.expired());
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)3000));
REQUIRE(fuzzycomp(delta, (timeType)3000));
Serial.print("reset\n");
timeout.reset(1000);
before = millis();
while (!timeout)
;
after = millis();
Serial.print("reset\n");
delta = after - before;
Serial.printf("delta = %lu\n", delta);
timeout.reset(1000);
before = millis();
while(!timeout);
after = millis();
delta = after - before;
Serial.printf("delta = %lu\n", delta);
REQUIRE(fuzzycomp(delta, (timeType)1000));
REQUIRE(fuzzycomp(delta, (timeType)1000));
}

View File

@ -27,19 +27,19 @@ TEST_CASE("Print::write overrides all compile properly", "[core][Print]")
REQUIRE(LittleFS.begin());
auto p = LittleFS.open("test.bin", "w");
REQUIRE(p);
uint8_t uint8 = 1;
uint16_t uint16 = 2;
uint32_t uint32 = 3;
size_t size = 4;
int8_t int8 = 1;
int16_t int16 = 2;
int32_t int32 = 3;
char c = 'h';
int i = 10;
long l = 11;
unsigned char uc = 20;
unsigned int ui = 21;
unsigned long ul = 22;
uint8_t uint8 = 1;
uint16_t uint16 = 2;
uint32_t uint32 = 3;
size_t size = 4;
int8_t int8 = 1;
int16_t int16 = 2;
int32_t int32 = 3;
char c = 'h';
int i = 10;
long l = 11;
unsigned char uc = 20;
unsigned int ui = 21;
unsigned long ul = 22;
p.write(uint8);
p.write(uint16);
p.write(uint32);
@ -60,7 +60,7 @@ TEST_CASE("Print::write overrides all compile properly", "[core][Print]")
p = LittleFS.open("test.bin", "r");
REQUIRE(p);
uint8_t buff[16];
int len = p.read(buff, 16);
int len = p.read(buff, 16);
p.close();
REQUIRE(len == 15);
REQUIRE(buff[0] == 1);

View File

@ -16,12 +16,11 @@
#include <catch.hpp>
#include <Updater.h>
// Use a SPIFFS file because we can't instantiate a virtual class like Print
TEST_CASE("Updater fails when writes overflow requested size", "[core][Updater]")
{
UpdaterClass *u;
uint8_t buff[6000];
UpdaterClass* u;
uint8_t buff[6000];
memset(buff, 0, sizeof(buff));
u = new UpdaterClass();
REQUIRE(u->begin(6000));

View File

@ -32,30 +32,35 @@ TEST_CASE("MD5Builder::add works as expected", "[core][MD5Builder]")
REQUIRE(builder.toString() == "9edb67f2b22c604fab13e2fd1d6056d7");
}
TEST_CASE("MD5Builder::addHexString works as expected", "[core][MD5Builder]")
{
WHEN("A char array is parsed"){
MD5Builder builder;
builder.begin();
const char * myPayload = "1234567890abcdeffedcba98765432106469676974616c7369676e61747572656170706c69636174696F6e73";
builder.addHexString(myPayload);
builder.calculate();
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
WHEN("A char array is parsed")
{
MD5Builder builder;
builder.begin();
const char* myPayload = "1234567890abcdeffedcba98765432106469676974616c7369676e617475726561"
"70706c69636174696F6e73";
builder.addHexString(myPayload);
builder.calculate();
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
}
WHEN("A Arduino String is parsed"){
MD5Builder builder;
builder.begin();
builder.addHexString(String("1234567890abcdeffedcba98765432106469676974616c7369676e61747572656170706c69636174696f6e73"));
builder.calculate();
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
WHEN("A Arduino String is parsed")
{
MD5Builder builder;
builder.begin();
builder.addHexString(String("1234567890abcdeffedcba98765432106469676974616c7369676e61747572"
"656170706c69636174696f6e73"));
builder.calculate();
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");
}
}
TEST_CASE("MD5Builder::addStream works", "[core][MD5Builder]"){
MD5Builder builder;
const char* str = "MD5Builder::addStream_works_longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong";
TEST_CASE("MD5Builder::addStream works", "[core][MD5Builder]")
{
MD5Builder builder;
const char* str = "MD5Builder::addStream_works_"
"longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong";
{
StreamString stream;
stream.print(str);

View File

@ -19,15 +19,16 @@
TEST_CASE("strstr_P works as strstr", "[core][pgmspace]")
{
auto t = [](const char* h, const char* n) {
auto t = [](const char* h, const char* n)
{
const char* strstr_P_result = strstr_P(h, n);
const char* strstr_result = strstr(h, n);
const char* strstr_result = strstr(h, n);
REQUIRE(strstr_P_result == strstr_result);
};
// Test case data is from avr-libc, original copyright (c) 2007 Dmitry Xmelkov
// See avr-libc/tests/simulate/pmstring/strstr_P.c
t ("", "");
t("", "");
t("12345", "");
t("ababac", "abac");
t("", "a");

View File

@ -43,8 +43,8 @@ TEST_CASE("String::trim", "[core][String]")
TEST_CASE("String::replace", "[core][String]")
{
String str;
str = "The quick brown fox jumped over the lazy dog.";
String find = "fox";
str = "The quick brown fox jumped over the lazy dog.";
String find = "fox";
String replace = "vulpes vulpes";
str.replace(find, replace);
REQUIRE(str == "The quick brown vulpes vulpes jumped over the lazy dog.");
@ -52,10 +52,10 @@ TEST_CASE("String::replace", "[core][String]")
TEST_CASE("String(value, base)", "[core][String]")
{
String strbase2(9999,2);
String strbase8(9999,8);
String strbase10(9999,10);
String strbase16(9999,16);
String strbase2(9999, 2);
String strbase8(9999, 8);
String strbase10(9999, 10);
String strbase16(9999, 16);
REQUIRE(strbase2 == "10011100001111");
REQUIRE(strbase8 == "23417");
REQUIRE(strbase10 == "9999");
@ -64,7 +64,7 @@ TEST_CASE("String(value, base)", "[core][String]")
String strnegf(-2.123, 3);
REQUIRE(strnegi == "-9999");
REQUIRE(strnegf == "-2.123");
String strbase16l((long)999999,16);
String strbase16l((long)999999, 16);
REQUIRE(strbase16l == "f423f");
}
@ -83,8 +83,8 @@ TEST_CASE("String constructors", "[core][String]")
String s1("abcd");
String s2(s1);
REQUIRE(s1 == s2);
String *s3 = new String("manos");
s2 = *s3;
String* s3 = new String("manos");
s2 = *s3;
delete s3;
REQUIRE(s2 == "manos");
s3 = new String("thisismuchlongerthantheother");
@ -97,8 +97,8 @@ TEST_CASE("String constructors", "[core][String]")
REQUIRE(ssh == "3.14159_abcd");
String flash = (F("hello from flash"));
REQUIRE(flash == "hello from flash");
const char textarray[6] = {'h', 'e', 'l', 'l', 'o', 0};
String hello(textarray);
const char textarray[6] = { 'h', 'e', 'l', 'l', 'o', 0 };
String hello(textarray);
REQUIRE(hello == "hello");
String hello2;
hello2 = textarray;
@ -135,13 +135,21 @@ TEST_CASE("String concantenation", "[core][String]")
str += LLONG_MIN;
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808");
str += String(LLONG_MIN, 10);
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808");
REQUIRE(str
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
"9223372036854775808");
str += LLONG_MAX;
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-92233720368547758089223372036854775807");
REQUIRE(str
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
"92233720368547758089223372036854775807");
str += ULLONG_MAX;
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808922337203685477580718446744073709551615");
REQUIRE(str
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
"9223372036854775808922337203685477580718446744073709551615");
str += String(ULLONG_MAX, 16);
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808922337203685477580718446744073709551615ffffffffffffffff");
REQUIRE(str
== "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-"
"9223372036854775808922337203685477580718446744073709551615ffffffffffffffff");
str = "clean";
REQUIRE(str.concat(str) == true);
REQUIRE(str == "cleanclean");
@ -156,19 +164,19 @@ TEST_CASE("String concantenation", "[core][String]")
REQUIRE(str == "-100");
// Non-zero-terminated array concatenation
const char buff[] = "abcdefg";
String n;
n = "1234567890"; // Make it a SSO string, fill with non-0 data
n = "1"; // Overwrite [1] with 0, but leave old junk in SSO space still
String n;
n = "1234567890"; // Make it a SSO string, fill with non-0 data
n = "1"; // Overwrite [1] with 0, but leave old junk in SSO space still
n.concat(buff, 3);
REQUIRE(n == "1abc"); // Ensure the trailing 0 is always present even w/this funky concat
for (int i=0; i<20; i++)
n.concat(buff, 1); // Add 20 'a's to go from SSO to normal string
REQUIRE(n == "1abc"); // Ensure the trailing 0 is always present even w/this funky concat
for (int i = 0; i < 20; i++)
n.concat(buff, 1); // Add 20 'a's to go from SSO to normal string
REQUIRE(n == "1abcaaaaaaaaaaaaaaaaaaaa");
n = "";
for (int i=0; i<=5; i++)
for (int i = 0; i <= 5; i++)
n.concat(buff, i);
REQUIRE(n == "aababcabcdabcde");
n.concat(buff, 0); // And check no add'n
n.concat(buff, 0); // And check no add'n
REQUIRE(n == "aababcabcdabcde");
}
@ -211,7 +219,7 @@ TEST_CASE("String byte access", "[core][String]")
TEST_CASE("String conversion", "[core][String]")
{
String s = "12345";
long l = s.toInt();
long l = s.toInt();
REQUIRE(l == 12345);
s = "2147483647";
l = s.toInt();
@ -222,9 +230,9 @@ TEST_CASE("String conversion", "[core][String]")
s = "-2147483648";
l = s.toInt();
REQUIRE(l == INT_MIN);
s = "3.14159";
s = "3.14159";
float f = s.toFloat();
REQUIRE( fabs(f - 3.14159) < 0.0001 );
REQUIRE(fabs(f - 3.14159) < 0.0001);
}
TEST_CASE("String case", "[core][String]")
@ -246,7 +254,7 @@ TEST_CASE("String nulls", "[core][String]")
s.trim();
s.toUpperCase();
s.toLowerCase();
s.remove(1,1);
s.remove(1, 1);
s.remove(10);
s.replace("taco", "burrito");
s.replace('a', 'b');
@ -268,7 +276,7 @@ TEST_CASE("String nulls", "[core][String]")
REQUIRE(s == "");
REQUIRE(s.length() == 0);
s.setCharAt(1, 't');
REQUIRE(s.startsWith("abc",0) == false);
REQUIRE(s.startsWith("abc", 0) == false);
REQUIRE(s.startsWith("def") == false);
REQUIRE(s.equalsConstantTime("def") == false);
REQUIRE(s.equalsConstantTime("") == true);
@ -299,125 +307,128 @@ TEST_CASE("String sizes near 8b", "[core][String]")
String s15("12345678901234");
String s16("123456789012345");
String s17("1234567890123456");
REQUIRE(!strcmp(s7.c_str(),"123456"));
REQUIRE(!strcmp(s8.c_str(),"1234567"));
REQUIRE(!strcmp(s9.c_str(),"12345678"));
REQUIRE(!strcmp(s15.c_str(),"12345678901234"));
REQUIRE(!strcmp(s16.c_str(),"123456789012345"));
REQUIRE(!strcmp(s17.c_str(),"1234567890123456"));
REQUIRE(!strcmp(s7.c_str(), "123456"));
REQUIRE(!strcmp(s8.c_str(), "1234567"));
REQUIRE(!strcmp(s9.c_str(), "12345678"));
REQUIRE(!strcmp(s15.c_str(), "12345678901234"));
REQUIRE(!strcmp(s16.c_str(), "123456789012345"));
REQUIRE(!strcmp(s17.c_str(), "1234567890123456"));
s7 += '_';
s8 += '_';
s9 += '_';
s15 += '_';
s16 += '_';
s17 += '_';
REQUIRE(!strcmp(s7.c_str(),"123456_"));
REQUIRE(!strcmp(s8.c_str(),"1234567_"));
REQUIRE(!strcmp(s9.c_str(),"12345678_"));
REQUIRE(!strcmp(s15.c_str(),"12345678901234_"));
REQUIRE(!strcmp(s16.c_str(),"123456789012345_"));
REQUIRE(!strcmp(s17.c_str(),"1234567890123456_"));
REQUIRE(!strcmp(s7.c_str(), "123456_"));
REQUIRE(!strcmp(s8.c_str(), "1234567_"));
REQUIRE(!strcmp(s9.c_str(), "12345678_"));
REQUIRE(!strcmp(s15.c_str(), "12345678901234_"));
REQUIRE(!strcmp(s16.c_str(), "123456789012345_"));
REQUIRE(!strcmp(s17.c_str(), "1234567890123456_"));
}
TEST_CASE("String SSO works", "[core][String]")
{
// This test assumes that SSO_SIZE==8, if that changes the test must as well
String s;
s += "0";
REQUIRE(s == "0");
REQUIRE(s.length() == 1);
const char *savesso = s.c_str();
s += 1;
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "01");
REQUIRE(s.length() == 2);
s += "2";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "012");
REQUIRE(s.length() == 3);
s += 3;
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123");
REQUIRE(s.length() == 4);
s += "4";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "01234");
REQUIRE(s.length() == 5);
s += "5";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "012345");
REQUIRE(s.length() == 6);
s += "6";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456");
REQUIRE(s.length() == 7);
s += "7";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "01234567");
REQUIRE(s.length() == 8);
s += "8";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "012345678");
REQUIRE(s.length() == 9);
s += "9";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456789");
REQUIRE(s.length() == 10);
if (sizeof(savesso) == 4) {
s += "a";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789a");
REQUIRE(s.length() == 11);
s += "b";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789ab");
REQUIRE(s.length() == 12);
s += "c";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abc");
REQUIRE(s.length() == 13);
} else {
s += "a";
// This test assumes that SSO_SIZE==8, if that changes the test must as well
String s;
s += "0";
REQUIRE(s == "0");
REQUIRE(s.length() == 1);
const char* savesso = s.c_str();
s += 1;
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456789a");
REQUIRE(s.length() == 11);
s += "bcde";
REQUIRE(s == "01");
REQUIRE(s.length() == 2);
s += "2";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456789abcde");
REQUIRE(s.length() == 15);
s += "fghi";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghi");
REQUIRE(s.length() == 19);
s += "j";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghij");
REQUIRE(s.length() == 20);
s += "k";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijk");
REQUIRE(s.length() == 21);
s += "l";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijkl");
REQUIRE(s.length() == 22);
s += "m";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijklm");
REQUIRE(s.length() == 23);
s += "nopq";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijklmnopq");
REQUIRE(s.length() == 27);
s += "rstu";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijklmnopqrstu");
REQUIRE(s.length() == 31);
}
s = "0123456789abcde";
s = s.substring(s.indexOf('a'));
REQUIRE(s == "abcde");
REQUIRE(s.length() == 5);
REQUIRE(s == "012");
REQUIRE(s.length() == 3);
s += 3;
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123");
REQUIRE(s.length() == 4);
s += "4";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "01234");
REQUIRE(s.length() == 5);
s += "5";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "012345");
REQUIRE(s.length() == 6);
s += "6";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456");
REQUIRE(s.length() == 7);
s += "7";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "01234567");
REQUIRE(s.length() == 8);
s += "8";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "012345678");
REQUIRE(s.length() == 9);
s += "9";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456789");
REQUIRE(s.length() == 10);
if (sizeof(savesso) == 4)
{
s += "a";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789a");
REQUIRE(s.length() == 11);
s += "b";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789ab");
REQUIRE(s.length() == 12);
s += "c";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abc");
REQUIRE(s.length() == 13);
}
else
{
s += "a";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456789a");
REQUIRE(s.length() == 11);
s += "bcde";
REQUIRE(s.c_str() == savesso);
REQUIRE(s == "0123456789abcde");
REQUIRE(s.length() == 15);
s += "fghi";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghi");
REQUIRE(s.length() == 19);
s += "j";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghij");
REQUIRE(s.length() == 20);
s += "k";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijk");
REQUIRE(s.length() == 21);
s += "l";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijkl");
REQUIRE(s.length() == 22);
s += "m";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijklm");
REQUIRE(s.length() == 23);
s += "nopq";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijklmnopq");
REQUIRE(s.length() == 27);
s += "rstu";
REQUIRE(s.c_str() != savesso);
REQUIRE(s == "0123456789abcdefghijklmnopqrstu");
REQUIRE(s.length() == 31);
}
s = "0123456789abcde";
s = s.substring(s.indexOf('a'));
REQUIRE(s == "abcde");
REQUIRE(s.length() == 5);
}
#include <new>
@ -426,70 +437,67 @@ void repl(const String& key, const String& val, String& s, boolean useURLencode)
s.replace(key, val);
}
TEST_CASE("String SSO handles junk in memory", "[core][String]")
{
// We fill the SSO space with garbage then construct an object in it and check consistency
// This is NOT how you want to use Strings outside of this testing!
unsigned char space[64];
String *s = (String*)space;
memset(space, 0xff, 64);
new(s) String;
REQUIRE(*s == "");
s->~String();
// We fill the SSO space with garbage then construct an object in it and check consistency
// This is NOT how you want to use Strings outside of this testing!
unsigned char space[64];
String* s = (String*)space;
memset(space, 0xff, 64);
new (s) String;
REQUIRE(*s == "");
s->~String();
// Tests from #5883
bool useURLencode = false;
const char euro[4] = {(char)0xe2, (char)0x82, (char)0xac, 0}; // Unicode euro symbol
const char yen[3] = {(char)0xc2, (char)0xa5, 0}; // Unicode yen symbol
// Tests from #5883
bool useURLencode = false;
const char euro[4] = { (char)0xe2, (char)0x82, (char)0xac, 0 }; // Unicode euro symbol
const char yen[3] = { (char)0xc2, (char)0xa5, 0 }; // Unicode yen symbol
memset(space, 0xff, 64);
new(s) String("%ssid%");
repl(("%ssid%"), "MikroTik", *s, useURLencode);
REQUIRE(*s == "MikroTik");
s->~String();
memset(space, 0xff, 64);
new (s) String("%ssid%");
repl(("%ssid%"), "MikroTik", *s, useURLencode);
REQUIRE(*s == "MikroTik");
s->~String();
memset(space, 0xff, 64);
new(s) String("{E}");
repl(("{E}"), euro, *s, useURLencode);
REQUIRE(*s == "");
s->~String();
memset(space, 0xff, 64);
new(s) String("&euro;");
repl(("&euro;"), euro, *s, useURLencode);
REQUIRE(*s == "");
s->~String();
memset(space, 0xff, 64);
new(s) String("{Y}");
repl(("{Y}"), yen, *s, useURLencode);
REQUIRE(*s == "¥");
s->~String();
memset(space, 0xff, 64);
new(s) String("&yen;");
repl(("&yen;"), yen, *s, useURLencode);
REQUIRE(*s == "¥");
s->~String();
memset(space, 0xff, 64);
new (s) String("{E}");
repl(("{E}"), euro, *s, useURLencode);
REQUIRE(*s == "");
s->~String();
memset(space, 0xff, 64);
new (s) String("&euro;");
repl(("&euro;"), euro, *s, useURLencode);
REQUIRE(*s == "");
s->~String();
memset(space, 0xff, 64);
new (s) String("{Y}");
repl(("{Y}"), yen, *s, useURLencode);
REQUIRE(*s == "¥");
s->~String();
memset(space, 0xff, 64);
new (s) String("&yen;");
repl(("&yen;"), yen, *s, useURLencode);
REQUIRE(*s == "¥");
s->~String();
memset(space, 0xff, 64);
new(s) String("%sysname%");
repl(("%sysname%"), "CO2_defect", *s, useURLencode);
REQUIRE(*s == "CO2_defect");
s->~String();
memset(space, 0xff, 64);
new (s) String("%sysname%");
repl(("%sysname%"), "CO2_defect", *s, useURLencode);
REQUIRE(*s == "CO2_defect");
s->~String();
}
TEST_CASE("Issue #5949 - Overlapping src/dest in replace", "[core][String]")
{
String blah = "blah";
blah.replace("xx", "y");
REQUIRE(blah == "blah");
blah.replace("x", "yy");
REQUIRE(blah == "blah");
blah.replace(blah, blah);
REQUIRE(blah == "blah");
String blah = "blah";
blah.replace("xx", "y");
REQUIRE(blah == "blah");
blah.replace("x", "yy");
REQUIRE(blah == "blah");
blah.replace(blah, blah);
REQUIRE(blah == "blah");
}
TEST_CASE("Issue #2736 - StreamString SSO fix", "[core][StreamString]")
{
StreamString s;
@ -502,102 +510,101 @@ TEST_CASE("Issue #2736 - StreamString SSO fix", "[core][StreamString]")
TEST_CASE("Strings with NULs", "[core][String]")
{
// The following should never be done in a real app! This is only to inject 0s in the middle of a string.
// Fits in SSO...
String str("01234567");
REQUIRE(str.length() == 8);
char *ptr = (char *)str.c_str();
ptr[3] = 0;
String str2;
str2 = str;
REQUIRE(str2.length() == 8);
// Needs a buffer pointer
str = "0123456789012345678901234567890123456789";
ptr = (char *)str.c_str();
ptr[3] = 0;
str2 = str;
REQUIRE(str2.length() == 40);
String str3("a");
ptr = (char *)str3.c_str();
*ptr = 0;
REQUIRE(str3.length() == 1);
str3 += str3;
REQUIRE(str3.length() == 2);
str3 += str3;
REQUIRE(str3.length() == 4);
str3 += str3;
REQUIRE(str3.length() == 8);
str3 += str3;
REQUIRE(str3.length() == 16);
str3 += str3;
REQUIRE(str3.length() == 32);
str3 += str3;
REQUIRE(str3.length() == 64);
static char zeros[64] = {0};
const char *p = str3.c_str();
REQUIRE(!memcmp(p, zeros, 64));
// The following should never be done in a real app! This is only to inject 0s in the middle of
// a string. Fits in SSO...
String str("01234567");
REQUIRE(str.length() == 8);
char* ptr = (char*)str.c_str();
ptr[3] = 0;
String str2;
str2 = str;
REQUIRE(str2.length() == 8);
// Needs a buffer pointer
str = "0123456789012345678901234567890123456789";
ptr = (char*)str.c_str();
ptr[3] = 0;
str2 = str;
REQUIRE(str2.length() == 40);
String str3("a");
ptr = (char*)str3.c_str();
*ptr = 0;
REQUIRE(str3.length() == 1);
str3 += str3;
REQUIRE(str3.length() == 2);
str3 += str3;
REQUIRE(str3.length() == 4);
str3 += str3;
REQUIRE(str3.length() == 8);
str3 += str3;
REQUIRE(str3.length() == 16);
str3 += str3;
REQUIRE(str3.length() == 32);
str3 += str3;
REQUIRE(str3.length() == 64);
static char zeros[64] = { 0 };
const char* p = str3.c_str();
REQUIRE(!memcmp(p, zeros, 64));
}
TEST_CASE("Replace and string expansion", "[core][String]")
{
String s, l;
// Make these large enough to span SSO and non SSO
String whole = "#123456789012345678901234567890";
const char *res = "abcde123456789012345678901234567890";
for (size_t i=1; i < whole.length(); i++) {
s = whole.substring(0, i);
l = s;
l.replace("#", "abcde");
char buff[64];
strcpy(buff, res);
buff[5 + i-1] = 0;
REQUIRE(!strcmp(l.c_str(), buff));
REQUIRE(l.length() == strlen(buff));
}
String s, l;
// Make these large enough to span SSO and non SSO
String whole = "#123456789012345678901234567890";
const char* res = "abcde123456789012345678901234567890";
for (size_t i = 1; i < whole.length(); i++)
{
s = whole.substring(0, i);
l = s;
l.replace("#", "abcde");
char buff[64];
strcpy(buff, res);
buff[5 + i - 1] = 0;
REQUIRE(!strcmp(l.c_str(), buff));
REQUIRE(l.length() == strlen(buff));
}
}
TEST_CASE("String chaining", "[core][String]")
{
const char* chunks[] {
"~12345",
"67890",
"qwertyuiopasdfghjkl",
"zxcvbnm"
};
const char* chunks[] { "~12345", "67890", "qwertyuiopasdfghjkl", "zxcvbnm" };
String all;
for (auto* chunk : chunks) {
all += chunk;
}
String all;
for (auto* chunk : chunks)
{
all += chunk;
}
// make sure we can chain a combination of things to form a String
REQUIRE((String(chunks[0]) + String(chunks[1]) + String(chunks[2]) + String(chunks[3])) == all);
REQUIRE((chunks[0] + String(chunks[1]) + F(chunks[2]) + chunks[3]) == all);
REQUIRE((String(chunks[0]) + F(chunks[1]) + F(chunks[2]) + String(chunks[3])) == all);
REQUIRE(('~' + String(&chunks[0][0] + 1) + chunks[1] + String(chunks[2]) + F(chunks[3])) == all);
REQUIRE((String(chunks[0]) + '6' + (&chunks[1][0] + 1) + String(chunks[2]) + F(chunks[3])) == all);
// make sure we can chain a combination of things to form a String
REQUIRE((String(chunks[0]) + String(chunks[1]) + String(chunks[2]) + String(chunks[3])) == all);
REQUIRE((chunks[0] + String(chunks[1]) + F(chunks[2]) + chunks[3]) == all);
REQUIRE((String(chunks[0]) + F(chunks[1]) + F(chunks[2]) + String(chunks[3])) == all);
REQUIRE(('~' + String(&chunks[0][0] + 1) + chunks[1] + String(chunks[2]) + F(chunks[3]))
== all);
REQUIRE((String(chunks[0]) + '6' + (&chunks[1][0] + 1) + String(chunks[2]) + F(chunks[3]))
== all);
// these are still invalid (and also cannot compile at all):
// - `F(...)` + `F(...)`
// - `F(...)` + `const char*`
// - `const char*` + `F(...)`
// we need `String()` as either rhs or lhs
// these are still invalid (and also cannot compile at all):
// - `F(...)` + `F(...)`
// - `F(...)` + `const char*`
// - `const char*` + `F(...)`
// we need `String()` as either rhs or lhs
// ensure chaining reuses the buffer
// (internal details...)
{
String tmp(chunks[3]);
tmp.reserve(2 * all.length());
auto* ptr = tmp.c_str();
String result("~1" + String(&chunks[0][0] + 2) + F(chunks[1]) + chunks[2] + std::move(tmp));
REQUIRE(result == all);
REQUIRE(static_cast<const void*>(result.c_str()) == static_cast<const void*>(ptr));
}
// ensure chaining reuses the buffer
// (internal details...)
{
String tmp(chunks[3]);
tmp.reserve(2 * all.length());
auto* ptr = tmp.c_str();
String result("~1" + String(&chunks[0][0] + 2) + F(chunks[1]) + chunks[2] + std::move(tmp));
REQUIRE(result == all);
REQUIRE(static_cast<const void*>(result.c_str()) == static_cast<const void*>(ptr));
}
}
TEST_CASE("String concat OOB #8198", "[core][String]")
{
char *p = (char*)malloc(16);
char* p = (char*)malloc(16);
memset(p, 'x', 16);
String s = "abcd";
s.concat(p, 16);

View File

@ -24,8 +24,8 @@
#include "../../../libraries/SDFS/src/SDFS.h"
#include "../../../libraries/SD/src/SD.h"
namespace spiffs_test {
namespace spiffs_test
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@ -47,9 +47,9 @@ namespace spiffs_test {
TEST_CASE("SPIFFS checks the config object passed in", "[fs]")
{
SPIFFS_MOCK_DECLARE(64, 8, 512, "");
FSConfig f;
SPIFFSConfig s;
SDFSConfig d;
FSConfig f;
SPIFFSConfig s;
SDFSConfig d;
LittleFSConfig l;
REQUIRE_FALSE(SPIFFS.setConfig(f));
@ -59,14 +59,15 @@ TEST_CASE("SPIFFS checks the config object passed in", "[fs]")
}
#pragma GCC diagnostic pop
};
}; // namespace spiffs_test
namespace littlefs_test {
namespace littlefs_test
{
#define FSTYPE LittleFS
#define TESTPRE "LittleFS - "
#define TESTPAT "[lfs]"
// LittleFS routines strip leading slashes before doing anything, so up to 31 char names are allowable
// LittleFS routines strip leading slashes before doing anything, so up to 31 char names are
// allowable
#define TOOLONGFILENAME "/12345678901234567890123456789012"
#define FS_MOCK_DECLARE LITTLEFS_MOCK_DECLARE
#define FS_MOCK_RESET LITTLEFS_MOCK_RESET
@ -82,9 +83,9 @@ namespace littlefs_test {
TEST_CASE("LittleFS checks the config object passed in", "[fs]")
{
LITTLEFS_MOCK_DECLARE(64, 8, 512, "");
FSConfig f;
SPIFFSConfig s;
SDFSConfig d;
FSConfig f;
SPIFFSConfig s;
SDFSConfig d;
LittleFSConfig l;
REQUIRE_FALSE(LittleFS.setConfig(f));
@ -93,17 +94,21 @@ TEST_CASE("LittleFS checks the config object passed in", "[fs]")
REQUIRE(LittleFS.setConfig(l));
}
};
}; // namespace littlefs_test
namespace sdfs_test {
namespace sdfs_test
{
#define FSTYPE SDFS
#define TESTPRE "SDFS - "
#define TESTPAT "[sdfs]"
// SDFS supports long paths (MAXPATH)
#define TOOLONGFILENAME "/" \
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" \
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" \
"12345678901234567890123456789012345678901234567890123456"
#define TOOLONGFILENAME \
"/" \
"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" \
"34567890" \
"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" \
"34567890" \
"12345678901234567890123456789012345678901234567890123456"
#define FS_MOCK_DECLARE SDFS_MOCK_DECLARE
#define FS_MOCK_RESET SDFS_MOCK_RESET
#define FS_HAS_DIRS
@ -118,9 +123,9 @@ namespace sdfs_test {
TEST_CASE("SDFS checks the config object passed in", "[fs]")
{
SDFS_MOCK_DECLARE(64, 8, 512, "");
FSConfig f;
SPIFFSConfig s;
SDFSConfig d;
FSConfig f;
SPIFFSConfig s;
SDFSConfig d;
LittleFSConfig l;
REQUIRE_FALSE(SDFS.setConfig(f));
@ -142,7 +147,7 @@ TEST_CASE("SD.h FILE_WRITE macro is append", "[fs]")
f.write(65);
f.write("bbcc");
f.write("theend", 6);
char block[3]={'x','y','z'};
char block[3] = { 'x', 'y', 'z' };
f.write(block, 3);
uint32_t bigone = 0x40404040;
f.write((const uint8_t*)&bigone, 4);
@ -155,11 +160,11 @@ TEST_CASE("SD.h FILE_WRITE macro is append", "[fs]")
File g = SD.open("/file2.txt", FILE_WRITE);
g.write(0);
g.close();
g = SD.open("/file2.txt", FILE_READ);
g = SD.open("/file2.txt", FILE_READ);
uint8_t u = 0x66;
g.read(&u, 1);
g.close();
REQUIRE(u == 0);
}
};
}; // namespace sdfs_test

View File

@ -15,11 +15,11 @@
#endif
#ifndef PGM_P
#define PGM_P const char *
#define PGM_P const char*
#endif
#ifndef PGM_VOID_P
#define PGM_VOID_P const void *
#define PGM_VOID_P const void*
#endif
#ifndef PSTR
@ -27,37 +27,49 @@
#endif
#ifdef __cplusplus
#define pgm_read_byte(addr) (*reinterpret_cast<const uint8_t*>(addr))
#define pgm_read_word(addr) (*reinterpret_cast<const uint16_t*>(addr))
#define pgm_read_dword(addr) (*reinterpret_cast<const uint32_t*>(addr))
#define pgm_read_float(addr) (*reinterpret_cast<const float*>(addr))
#define pgm_read_ptr(addr) (*reinterpret_cast<const void* const *>(addr))
#define pgm_read_byte(addr) (*reinterpret_cast<const uint8_t*>(addr))
#define pgm_read_word(addr) (*reinterpret_cast<const uint16_t*>(addr))
#define pgm_read_dword(addr) (*reinterpret_cast<const uint32_t*>(addr))
#define pgm_read_float(addr) (*reinterpret_cast<const float*>(addr))
#define pgm_read_ptr(addr) (*reinterpret_cast<const void* const*>(addr))
#else
#define pgm_read_byte(addr) (*(const uint8_t*)(addr))
#define pgm_read_word(addr) (*(const uint16_t*)(addr))
#define pgm_read_dword(addr) (*(const uint32_t*)(addr))
#define pgm_read_float(addr) (*(const float)(addr))
#define pgm_read_ptr(addr) (*(const void* const *)(addr))
#define pgm_read_byte(addr) (*(const uint8_t*)(addr))
#define pgm_read_word(addr) (*(const uint16_t*)(addr))
#define pgm_read_dword(addr) (*(const uint32_t*)(addr))
#define pgm_read_float(addr) (*(const float)(addr))
#define pgm_read_ptr(addr) (*(const void* const*)(addr))
#endif
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
// Wrapper inlines for _P functions
#include <stdio.h>
#include <string.h>
inline const char *strstr_P(const char *haystack, const char *needle) { return strstr(haystack, needle); }
inline char *strcpy_P(char *dest, const char *src) { return strcpy(dest, src); }
inline size_t strlen_P(const char *s) { return strlen(s); }
inline int vsnprintf_P(char *str, size_t size, const char *format, va_list ap) { return vsnprintf(str, size, format, ap); }
inline const char* strstr_P(const char* haystack, const char* needle)
{
return strstr(haystack, needle);
}
inline char* strcpy_P(char* dest, const char* src)
{
return strcpy(dest, src);
}
inline size_t strlen_P(const char* s)
{
return strlen(s);
}
inline int vsnprintf_P(char* str, size_t size, const char* format, va_list ap)
{
return vsnprintf(str, size, format, ap);
}
#define memcpy_P memcpy
#define memmove_P memmove

View File

@ -1,19 +0,0 @@
#!/bin/sh
set -e
org=$(cd ${0%/*}; pwd)
cd ${org}/..
pwd
test -d cores/esp8266
test -d libraries
# in a near future, restyle-all.sh will be renamed to restyle.sh
# and will be checked against CI
for d in libraries; do
find $d -name "*.ino" -exec \
astyle \
--suffix=none \
--options=${org}/astyle_examples.conf {} \;
done

View File

@ -1,50 +1,64 @@
#!/bin/sh
# requires clang-format, git, python3 with pyyaml
set -e
set -e -x
org=$(cd ${0%/*}; pwd)
cd ${org}/..
pwd
test -d cores/esp8266
test -d libraries
root=$(git rev-parse --show-toplevel)
test -d ${root}/cores/esp8266
test -d ${root}/libraries
# should be: all="cores/esp8266 libraries"
# allow `env CLANG_FORMAT=clang-format-13`, or some other version
# default to v13, latest stable version from https://apt.llvm.org
CLANG_FORMAT=${CLANG_FORMAT:-clang-format-13}
all="
# TODO: waiting for llvm-14 to allow --style=file:<path-to-file>
makeClangFormatStyle() {
python3 -c 'import sys,yaml; sys.stdout.write(yaml.dump(yaml.safe_load(open(sys.argv[1], "r")), default_flow_style=True)); sys.stdout.flush();' $1
}
#########################################
# 'all' variable should be "cores/esp8266 libraries"
all=${1:-"
cores/esp8266/Lwip*
libraries/ESP8266mDNS
libraries/Wire
libraries/lwIP*
cores/esp8266/Lwip*
cores/esp8266/debug*
cores/esp8266/core_esp8266_si2c.cpp
cores/esp8266/StreamString.*
cores/esp8266/StreamSend.*
libraries/Netdump
"
tests
"}
# core
#########################################
# restyling core & libraries
for d in $all; do
if [ -d "$d" ]; then
echo "-------- directory $d:"
for e in c cpp h; do
find $d -name "*.$e" -exec \
astyle \
--suffix=none \
--options=${org}/astyle_core.conf {} \;
done
cd $root
style=$(makeClangFormatStyle ${root}/tests/clang-format-core.yaml)
for target in $all; do
if [ -d "$target" ]; then
find $target \
'(' -name "*.cpp" -o -name "*.c" -o -name "*.h" ')' \
-exec $CLANG_FORMAT --verbose --style="$style" -i {} \;
else
echo "-------- file $d:"
astyle --suffix=none --options=${org}/astyle_core.conf "$d"
$CLANG_FORMAT --verbose --style="$style" -i $target
fi
done
# examples
#########################################
# restyling arduino examples
for d in libraries; do
echo "-------- examples in $d:"
find $d -name "*.ino" -exec \
astyle \
--suffix=none \
--options=${org}/astyle_examples.conf {} \;
done
# TODO should not be matched, these are formatted externally
# exclude=$(git submodule --quiet foreach git rev-parse --show-toplevel | grep libraries)
style=$(makeClangFormatStyle ${root}/tests/clang-format-arduino.yaml)
find libraries \
-path libraries/ESP8266SdFat -prune -o \
-path libraries/Ethernet -prune -o \
-path libraries/SoftwareSerial -prune -o \
-name '*.ino' -exec $CLANG_FORMAT --verbose --style="$style" -i {} \;
#########################################

View File

@ -115,7 +115,8 @@ elif [ "$BUILD_TYPE" = host ]; then
tests/ci/host_test.sh
elif [ "$BUILD_TYPE" = style ]; then
tests/ci/install_astyle.sh
tests/ci/check_restyle.sh
tests/restyle.sh
else
echo "BUILD_TYPE not set or invalid"