Skip to content

Commit 520233f

Browse files
authored
Test: fixing itoa implementation and clean-up of tests and test Makefile (#8531)
* Test: fixing itoa implementation, clean-up of tests and test runner Update itoa to be the same as newlib, fixing edgecase of abs(INT_MIN) Update WString.cpp:toString() integer conversions to use noniso funcs Remove legacy gcc versions from Makefile and allow overrides Don't fallback to c11 and c++11, source cannot support that * CXX and CC are make predefined values, assuming ?= does not work (?)
1 parent 27827c8 commit 520233f

File tree

7 files changed

+117
-86
lines changed

7 files changed

+117
-86
lines changed

cores/esp8266/WString.cpp

+16-35
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "WString.h"
2626
#include "stdlib_noniso.h"
2727

28+
#include <limits>
29+
2830
#define OOM_STRING_BORDER_DISPLAY 10
2931
#define OOM_STRING_THRESHOLD_REALLOC_WARN 128
3032

@@ -38,7 +40,7 @@
3840
static String toString(unsigned char value, unsigned char base) {
3941
String out;
4042

41-
char buf[1 + 8 * sizeof(unsigned char)];
43+
char buf[1 + std::numeric_limits<unsigned char>::digits];
4244
out = utoa(value, buf, base);
4345

4446
return out;
@@ -47,20 +49,16 @@ static String toString(unsigned char value, unsigned char base) {
4749
static String toString(int value, unsigned char base) {
4850
String out;
4951

50-
char buf[2 + 8 * sizeof(int)];
51-
if (base == 10) {
52-
out.concat(buf, sprintf(buf, "%d", value));
53-
} else {
54-
out = itoa(value, buf, base);
55-
}
52+
char buf[2 + std::numeric_limits<int>::digits];
53+
out = itoa(value, buf, base);
5654

5755
return out;
5856
}
5957

6058
static String toString(unsigned int value, unsigned char base) {
6159
String out;
6260

63-
char buf[1 + 8 * sizeof(unsigned int)];
61+
char buf[1 + std::numeric_limits<unsigned int>::digits];
6462
out = utoa(value, buf, base);
6563

6664
return out;
@@ -69,20 +67,16 @@ static String toString(unsigned int value, unsigned char base) {
6967
static String toString(long value, unsigned char base) {
7068
String out;
7169

72-
char buf[2 + 8 * sizeof(long)];
73-
if (base == 10) {
74-
out.concat(buf, sprintf(buf, "%ld", value));
75-
} else {
76-
out = ltoa(value, buf, base);
77-
}
70+
char buf[2 + std::numeric_limits<long>::digits];
71+
out = ltoa(value, buf, base);
7872

7973
return out;
8074
}
8175

8276
static String toString(unsigned long value, unsigned char base) {
8377
String out;
8478

85-
char buf[1 + 8 * sizeof(unsigned long)];
79+
char buf[1 + std::numeric_limits<unsigned long>::digits];
8680
out = ultoa(value, buf, base);
8781

8882
return out;
@@ -93,30 +87,22 @@ static String toString(unsigned long value, unsigned char base) {
9387
static String toString(long long value, unsigned char base) {
9488
String out;
9589

96-
char buf[2 + 8 * sizeof(long long)];
97-
if (base == 10) {
98-
out.concat(buf, sprintf(buf, "%lld", value));
99-
} else {
100-
out = lltoa(value, buf, sizeof(buf), base);
101-
}
90+
char buf[2 + std::numeric_limits<long long>::digits];
91+
out = lltoa(value, buf, sizeof(buf), base);
10292

10393
return out;
10494
}
10595

10696
static String toString(unsigned long long value, unsigned char base) {
10797
String out;
10898

109-
char buf[1 + 8 * sizeof(unsigned long long)];
110-
if (base == 10) {
111-
out.concat(buf, sprintf(buf, "%llu", value));
112-
} else {
113-
out = ulltoa(value, buf, sizeof(buf), base);
114-
}
99+
char buf[1 + std::numeric_limits<unsigned long long>::digits];
100+
out = ulltoa(value, buf, sizeof(buf), base);
115101

116102
return out;
117103
}
118104

119-
static String toString(float value, unsigned char decimalPlaces) {
105+
static String toString(double value, unsigned char decimalPlaces) {
120106
String out;
121107

122108
char buf[33];
@@ -125,13 +111,8 @@ static String toString(float value, unsigned char decimalPlaces) {
125111
return out;
126112
}
127113

128-
static String toString(double value, unsigned char decimalPlaces) {
129-
String out;
130-
131-
char buf[33];
132-
out = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
133-
134-
return out;
114+
static String toString(float value, unsigned char decimalPlaces) {
115+
return toString(static_cast<double>(value), decimalPlaces);
135116
}
136117

137118
/*********************************************/

cores/esp8266/WString.h

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class String {
5858
String(const String &str);
5959
String(const __FlashStringHelper *str);
6060
String(String &&rval) noexcept;
61+
6162
explicit String(char c) {
6263
sso.buff[0] = c;
6364
sso.buff[1] = 0;

tests/host/Makefile

+18-23
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,23 @@ RANLIB ?= ranlib
1212

1313
MAKEFILE = $(word 1, $(MAKEFILE_LIST))
1414

15-
CXX = $(shell for i in g++-10 g++-9 g++-8 g++; do which $$i > /dev/null && { echo $$i; break; } done)
16-
CC = $(shell for i in gcc-10 gcc-9 gcc-8 gcc; do which $$i > /dev/null && { echo $$i; break; } done)
17-
GCOV = $(shell for i in gcov-10 gcov-9 gcov-8 gcov; do which $$i > /dev/null && { echo $$i; break; } done)
18-
$(warning using $(CXX))
19-
ifeq ($(CXX),g++)
20-
CXXFLAGS += -std=gnu++11
21-
else
22-
CXXFLAGS += -std=gnu++17
23-
endif
24-
ifeq ($(CC),gcc)
25-
CFLAGS += -std=gnu11
26-
else
27-
CFLAGS += -std=gnu17
28-
endif
15+
# Prefer named GCC (and, specifically, GCC10), same as platform.txt / platformio_build.py
16+
find_tool = $(shell for name in $(1) $(2); do which $$name && break; done 2>/dev/null)
17+
CXX = $(call find_tool,g++-10,g++)
18+
CC = $(call find_tool,gcc-10,gcc)
19+
GCOV = $(call find_tool,gcov-10,gcov)
2920

30-
# I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X
31-
ifeq ($(shell uname -s),Darwin)
32-
CC ?= gcc
33-
CXX ?= g++
34-
endif
35-
GCOV ?= gcov
21+
$(warning using $(CXX) and $(CC))
22+
23+
GCOV ?= gcov
3624
VALGRIND ?= valgrind
37-
LCOV ?= lcov --gcov-tool $(GCOV)
38-
GENHTML ?= genhtml
25+
LCOV ?= lcov --gcov-tool $(GCOV)
26+
GENHTML ?= genhtml
27+
28+
# Board fild will be built with GCC10, but we have some limited ability to build with older versions
29+
# *Always* push the standard used in the platform.txt
30+
CXXFLAGS += -std=gnu++17
31+
CFLAGS += -std=gnu17
3932

4033
ifeq ($(FORCE32),1)
4134
SIZEOFLONG = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;)
@@ -174,6 +167,8 @@ INC_PATHS += \
174167
../../tools/sdk/lwip2/include \
175168
)
176169

170+
TEST_ARGS ?=
171+
177172
TEST_CPP_FILES := \
178173
fs/test_fs.cpp \
179174
core/test_pgmspace.cpp \
@@ -236,7 +231,7 @@ CI: # run CI
236231
doCI: build-info $(OUTPUT_BINARY) valgrind test gcov
237232

238233
test: $(OUTPUT_BINARY) # run host test for CI
239-
$(OUTPUT_BINARY)
234+
$(OUTPUT_BINARY) $(TEST_ARGS)
240235

241236
.PHONY: clean
242237
clean: clean-lcov clean-objects

tests/host/common/ArduinoCatch.cpp

+22-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,25 @@
1414
*/
1515

1616
#define CATCH_CONFIG_MAIN
17-
#include <catch.hpp>
18-
#include <sys/time.h>
19-
#include "Arduino.h"
17+
#include "ArduinoCatch.hpp"
18+
19+
std::ostream& operator<<(std::ostream& out, const String& str)
20+
{
21+
out.write(str.c_str(), str.length());
22+
return out;
23+
}
24+
25+
namespace Catch
26+
{
27+
28+
std::string toString(const String& str)
29+
{
30+
return std::string(str.begin(), str.length());
31+
}
32+
33+
std::string StringMaker<String>::convert(String const& str)
34+
{
35+
return toString(str);
36+
}
37+
38+
} // namespace Catch

tests/host/common/ArduinoCatch.hpp

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Arduino.cpp - Mocks for common Arduino APIs
3+
Copyright © 2016 Ivan Grokhotkov
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
*/
15+
16+
#include <Arduino.h>
17+
#include <sys/time.h>
18+
19+
#include <ostream>
20+
21+
#include "catch.hpp"
22+
23+
// Since Catch does not know about Arduino types, help it out so we could have these displayed in the tests output
24+
25+
std::ostream& operator<<(std::ostream&, const String&);
26+
27+
namespace Catch {
28+
29+
std::string toString(const String&);
30+
31+
template<>
32+
struct StringMaker<String> {
33+
static std::string convert(const String&);
34+
};
35+
36+
} // namespace Catch

tests/host/common/noniso.c

+14-19
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,24 @@ char* itoa(int value, char* result, int base)
6565
*result = 0;
6666
return result;
6767
}
68-
if (base != 10)
69-
{
70-
return utoa((unsigned)value, result, base);
71-
}
7268

73-
char* out = result;
74-
int quotient = abs(value);
69+
unsigned uvalue;
70+
char* out = result;
7571

76-
do
72+
// after this point we convert the value to unsigned and go to the utoa
73+
// only base10 gets minus sign in the front, adhering to the newlib implementation
74+
if ((base == 10) && (value < 0))
7775
{
78-
const int tmp = quotient / base;
79-
*out = "0123456789abcdef"[quotient - (tmp * base)];
80-
++out;
81-
quotient = tmp;
82-
} while (quotient);
83-
84-
// Apply negative sign
85-
if (value < 0)
86-
*out++ = '-';
76+
*result++ = '-';
77+
uvalue = (unsigned)-value;
78+
}
79+
else
80+
{
81+
uvalue = (unsigned)value;
82+
}
8783

88-
reverse(result, out);
89-
*out = 0;
90-
return result;
84+
utoa(uvalue, result, base);
85+
return out;
9186
}
9287

9388
int atoi(const char* s)

tests/host/core/test_string.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
all copies or substantial portions of the Software.
1414
*/
1515

16-
#include <catch.hpp>
17-
#include <string.h>
18-
#include <WString.h>
19-
#include <limits.h>
16+
#include <ArduinoCatch.hpp>
2017
#include <StreamString.h>
2118

19+
#include <string>
20+
#include <cstring>
21+
#include <limits>
22+
#include <climits>
23+
2224
TEST_CASE("String::move", "[core][String]")
2325
{
2426
const char buffer[] = "this string goes over the sso limit";
@@ -117,8 +119,10 @@ TEST_CASE("String concantenation", "[core][String]")
117119
str += "bcde";
118120
str += str;
119121
str += 987;
120-
str += (int)INT_MAX;
121-
str += (int)INT_MIN;
122+
REQUIRE(str == "abcdeabcde987");
123+
str += std::numeric_limits<int>::max();
124+
REQUIRE(str == "abcdeabcde9872147483647");
125+
str += std::numeric_limits<int>::min();
122126
REQUIRE(str == "abcdeabcde9872147483647-2147483648");
123127
str += (unsigned char)69;
124128
REQUIRE(str == "abcdeabcde9872147483647-214748364869");

0 commit comments

Comments
 (0)