Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 03ea61a

Browse files
earlephilhowerdevyte
authored andcommitted
Add valgrind and string tests to host_tests (#4939)
* Add valgrind and string tests to host_tests Valgrind identified an error that was causing intermittent failures in the host tests, and can check for subtle memory access and allocation bugs. Add it to the standard host_test suite, and any errors will cause test failure. Also start adding string tests, since two undefined behaviors have been found so far just by inspection. * Add additional String tests Looks like a possible bug in the concatenation operator, need to verify expected behavior. * Remove verbose from valgrind run No need to be so chatty on the test. Errors were a little hard to spot. Go to normal verbosity. * Add lcov and more string tests LCOV and genhtml can generate nice HTML coverage charts hilighting test coverage issues in a much simpler way than gcov text format. Generate these automatically from gcov output. Add additional string creation and comparison tests. * Move String coverage to >50% Additional string tests and checks * 66% test coverage in String * Add allocation-unit-sized strings test Ensure that strings that are right on the edge of the allocation size are handled properly and account for trailing 0.
1 parent 3cc12b1 commit 03ea61a

File tree

5 files changed

+282
-6
lines changed

5 files changed

+282
-6
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ tools/sdk/lwip/src/liblwip_src.a
1111
tools/sdk/ld/backup
1212
tools/sdk/ld/eagle.app.v6.common.ld
1313

14+
tests/hosts/lcov/
15+
1416
*.pyc
1517
*.gch
1618

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ install:
3838
}
3939
make -C $HOME/astyle/build/gcc prefix=$HOME install;
4040
} || true
41+
- sudo apt-get install valgrind lcov
4142

4243
script:
4344
- $TRAVIS_BUILD_DIR/tests/common.sh

tests/host/Makefile

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
BINARY_DIRECTORY := bin
2+
LCOV_DIRECTORY := lcov
23
OUTPUT_BINARY := $(BINARY_DIRECTORY)/host_tests
34
CORE_PATH := ../../cores/esp8266
45

@@ -8,6 +9,9 @@ CC ?= gcc
89
CXX ?= g++
910
endif
1011
GCOV ?= gcov
12+
VALGRIND ?= valgrind
13+
LCOV ?= lcov
14+
GENHTML ?= genhtml
1115

1216
CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\
1317
StreamString.cpp \
@@ -49,11 +53,12 @@ TEST_CPP_FILES := \
4953
fs/test_fs.cpp \
5054
core/test_pgmspace.cpp \
5155
core/test_md5builder.cpp \
56+
core/test_string.cpp
5257

53-
54-
CXXFLAGS += -std=c++11 -Wall -coverage -O0 -fno-common
55-
CFLAGS += -std=c99 -Wall -coverage -O0 -fno-common
58+
CXXFLAGS += -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g
59+
CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g
5660
LDFLAGS += -coverage -O0
61+
VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999
5762

5863
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))
5964

@@ -69,7 +74,7 @@ CPP_OBJECTS = $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_TESTS)
6974
OBJECTS = $(C_OBJECTS) $(CPP_OBJECTS)
7075
COVERAGE_FILES = $(OBJECTS:.o=.gc*)
7176

72-
all: build-info $(OUTPUT_BINARY) test gcov
77+
all: build-info $(OUTPUT_BINARY) valgrind test gcov
7378

7479
test: $(OUTPUT_BINARY)
7580
$(OUTPUT_BINARY)
@@ -81,11 +86,18 @@ clean-objects:
8186
rm -rf $(OBJECTS)
8287

8388
clean-coverage:
84-
rm -rf $(COVERAGE_FILES) *.gcov
89+
rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov
8590

8691
gcov: test
8792
find $(CORE_PATH) -name "*.gcno" -exec $(GCOV) -r -pb {} +
8893

94+
valgrind: $(OUTPUT_BINARY)
95+
mkdir -p $(LCOV_DIRECTORY)
96+
$(LCOV) --directory ../../cores/esp8266/ --zerocounters
97+
$(VALGRIND) $(VALGRINDFLAGS) $(OUTPUT_BINARY)
98+
$(LCOV) --directory $(CORE_PATH) --capture --output-file $(LCOV_DIRECTORY)/app.info
99+
$(GENHTML) $(LCOV_DIRECTORY)/app.info -o $(LCOV_DIRECTORY)
100+
89101
build-info:
90102
@echo "-------- build tools info --------"
91103
@echo "CC: " $(CC)

tests/host/core/test_md5builder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ TEST_CASE("MD5Builder::addHexString works as expected", "[core][MD5Builder]")
3838
WHEN("A char array is parsed"){
3939
MD5Builder builder;
4040
builder.begin();
41-
const char * myPayload = "1234567890abcdeffedcba98765432106469676974616c7369676e61747572656170706c69636174696f6e73";
41+
const char * myPayload = "1234567890abcdeffedcba98765432106469676974616c7369676e61747572656170706c69636174696F6e73";
4242
builder.addHexString(myPayload);
4343
builder.calculate();
4444
REQUIRE(builder.toString() == "47b937a6f9f12a4c389fa5854e023efb");

tests/host/core/test_string.cpp

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
/*
2+
test_string.cpp - String tests
3+
Copyright © 2018 Earle F. Philhower, III
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 <catch.hpp>
17+
#include <string.h>
18+
#include <WString.h>
19+
#include <limits.h>
20+
21+
TEST_CASE("String::trim", "[core][String]")
22+
{
23+
String str;
24+
str = " abcd123 ";
25+
str.trim();
26+
REQUIRE(str == "abcd123");
27+
}
28+
29+
TEST_CASE("String::replace", "[core][String]")
30+
{
31+
String str;
32+
str = "The quick brown fox jumped over the lazy dog.";
33+
String find = "fox";
34+
String replace = "vulpes vulpes";
35+
str.replace(find, replace);
36+
REQUIRE(str == "The quick brown vulpes vulpes jumped over the lazy dog.");
37+
}
38+
39+
TEST_CASE("String(value, base)", "[core][String]")
40+
{
41+
String strbase2(9999,2);
42+
String strbase8(9999,8);
43+
String strbase10(9999,10);
44+
String strbase16(9999,16);
45+
REQUIRE(strbase2 == "10011100001111");
46+
REQUIRE(strbase8 == "23417");
47+
REQUIRE(strbase10 == "9999");
48+
REQUIRE(strbase16 == "270f");
49+
String strnegi(-9999);
50+
String strnegf(-2.123, 3);
51+
REQUIRE(strnegi == "-9999");
52+
REQUIRE(strnegf == "-2.123");
53+
String strbase16l((long)999999,16);
54+
REQUIRE(strbase16l == "f423f");
55+
}
56+
57+
TEST_CASE("String constructors", "[core][String]")
58+
{
59+
String s0('c');
60+
REQUIRE(s0 == "c");
61+
String bin((unsigned char)5, 4);
62+
REQUIRE(bin == "11");
63+
String ib((unsigned int)999, 16);
64+
REQUIRE(ib == "3e7");
65+
String lb((unsigned long)3000000000, 8);
66+
REQUIRE(lb == "26264057000");
67+
String sl1((long)-2000000000, 10);
68+
REQUIRE(sl1 == "-2000000000");
69+
String s1("abcd");
70+
String s2(s1);
71+
REQUIRE(s1 == s2);
72+
String *s3 = new String("manos");
73+
s2 = *s3;
74+
delete s3;
75+
REQUIRE(s2 == "manos");
76+
s3 = new String("thisismuchlongerthantheother");
77+
s2 = s3->c_str();
78+
delete s3;
79+
REQUIRE(s2 == "thisismuchlongerthantheother");
80+
String strf((float)3.14159, 5);
81+
REQUIRE(strf == "3.14159");
82+
String ssh(strf + "_" + s1);
83+
REQUIRE(ssh == "3.14159_abcd");
84+
String flash = (F("hello from flash"));
85+
REQUIRE(flash == "hello from flash");
86+
}
87+
88+
TEST_CASE("String concantenation", "[core][String]")
89+
{
90+
String str;
91+
REQUIRE(str.length() == 0);
92+
str.reserve(1000);
93+
REQUIRE(str.length() == 0);
94+
str.reserve(0);
95+
REQUIRE(str.length() == 0);
96+
str += 'a';
97+
str += "bcde";
98+
str += str;
99+
str += 987;
100+
str += (int)INT_MAX;
101+
str += (int)INT_MIN;
102+
REQUIRE(str == "abcdeabcde9872147483647-2147483648");
103+
str += (unsigned char)69;
104+
REQUIRE(str == "abcdeabcde9872147483647-214748364869");
105+
str += (unsigned int)1969;
106+
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969");
107+
str += (long)-123;
108+
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123");
109+
str += (unsigned long)321;
110+
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321");
111+
str += (float)-1.01;
112+
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.01");
113+
str += (double)1.01;
114+
REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01");
115+
str = "clean";
116+
REQUIRE(str.concat(str) == true);
117+
REQUIRE(str == "cleanclean");
118+
}
119+
120+
TEST_CASE("String comparison", "[core][String]")
121+
{
122+
String alpha("I like fish!");
123+
REQUIRE(alpha < "I like tacos!");
124+
REQUIRE(alpha > "I like bacon!");
125+
REQUIRE(alpha.equalsIgnoreCase("i LiKe FiSh!"));
126+
REQUIRE(alpha.equalsConstantTime("I like fish!"));
127+
REQUIRE(alpha != "I like fish?");
128+
REQUIRE(alpha.startsWith("I like"));
129+
REQUIRE(!alpha.startsWith("I lick"));
130+
REQUIRE(alpha.startsWith("fish", 7));
131+
REQUIRE(!alpha.startsWith("fish?", 7));
132+
REQUIRE(alpha.endsWith("!"));
133+
REQUIRE(alpha.endsWith("fish!"));
134+
REQUIRE(!alpha.endsWith("sh?"));
135+
}
136+
137+
TEST_CASE("String byte access", "[core][String]")
138+
{
139+
String s;
140+
s.reserve(1000);
141+
s = "Never Eat Soggy Waffles";
142+
REQUIRE(s[0] == 'N');
143+
REQUIRE(s[999] == 0);
144+
s[6] = 'C';
145+
REQUIRE(!strcmp(s.c_str(), "Never Cat Soggy Waffles"));
146+
unsigned char buff[4];
147+
s.getBytes(buff, 4, 6);
148+
REQUIRE(!memcmp(buff, "Cat", 4));
149+
s = "Never E";
150+
memset(buff, 0, 4);
151+
s.getBytes(buff, 4, 6);
152+
bool ok = (buff[0] == 'E') && (buff[1] == 0) && (buff[2] == 0) && (buff[3] == 0);
153+
REQUIRE(ok == true);
154+
}
155+
156+
TEST_CASE("String conversion", "[core][String]")
157+
{
158+
String s = "12345";
159+
long l = s.toInt();
160+
REQUIRE(l == 12345);
161+
s = "2147483647";
162+
l = s.toInt();
163+
REQUIRE(l == INT_MAX);
164+
s = "-2147483647";
165+
l = s.toInt();
166+
REQUIRE(l == -2147483647);
167+
s = "-2147483648";
168+
l = s.toInt();
169+
REQUIRE(l == INT_MIN);
170+
s = "3.14159";
171+
float f = s.toFloat();
172+
REQUIRE( fabs(f - 3.14159) < 0.0001 );
173+
}
174+
175+
TEST_CASE("String case", "[core][String]")
176+
{
177+
String s = "aBc_123";
178+
s.toLowerCase();
179+
REQUIRE(s == "abc_123");
180+
s = "aBc_123";
181+
s.toUpperCase();
182+
REQUIRE(s == "ABC_123");
183+
}
184+
185+
TEST_CASE("String nulls", "[core][String]")
186+
{
187+
String s;
188+
REQUIRE(s == "");
189+
REQUIRE(s.toFloat() == 0);
190+
REQUIRE(s.toInt() == 0);
191+
s.trim();
192+
s.toUpperCase();
193+
s.toLowerCase();
194+
s.remove(1,1);
195+
s.remove(10);
196+
s.replace("taco", "burrito");
197+
s.replace('a', 'b');
198+
REQUIRE(s.substring(10, 20) == "");
199+
REQUIRE(s.lastIndexOf("tacos", 1) == -1);
200+
REQUIRE(s.lastIndexOf("tacos") == -1);
201+
REQUIRE(s.lastIndexOf('t', 0) == -1);
202+
REQUIRE(s.lastIndexOf('t') == -1);
203+
REQUIRE(s.indexOf("tacos", 1) == -1);
204+
REQUIRE(s.indexOf("tacos") == -1);
205+
REQUIRE(s.indexOf('t', 1) == -1);
206+
REQUIRE(s.indexOf('t') == -1);
207+
s.getBytes(NULL, 100, 0);
208+
s[0] = 't';
209+
REQUIRE(s == "");
210+
REQUIRE(s.length() == 0);
211+
s.setCharAt(1, 't');
212+
REQUIRE(s.startsWith("abc",0) == false);
213+
REQUIRE(s.startsWith("def") == false);
214+
REQUIRE(s.equalsConstantTime("def") == false);
215+
REQUIRE(s.equalsConstantTime("") == true);
216+
REQUIRE(s.equalsConstantTime(s) == true);
217+
REQUIRE(s.equalsIgnoreCase(s) == true);
218+
REQUIRE(s.equals("def") == false);
219+
REQUIRE(s.equals("") == true);
220+
REQUIRE(s.equals(s) == true);
221+
String t = s;
222+
REQUIRE(s.equals(t) == true);
223+
REQUIRE((s <= ""));
224+
REQUIRE(!(s < ""));
225+
REQUIRE((s >= ""));
226+
REQUIRE(!(s > ""));
227+
s += "abc";
228+
REQUIRE(s == "abc");
229+
}
230+
231+
TEST_CASE("String sizes near 8b", "[core][String]")
232+
{
233+
// Test that proper amount of space allocated (including trailing 0)
234+
// Need valgrind to verify no out-of-bounds errors, the strcmp()s will
235+
// access each byte and cause an exception of the space was not properly
236+
// allocated.
237+
String s7("123456");
238+
String s8("1234567");
239+
String s9("12345678");
240+
String s15("12345678901234");
241+
String s16("123456789012345");
242+
String s17("1234567890123456");
243+
REQUIRE(!strcmp(s7.c_str(),"123456"));
244+
REQUIRE(!strcmp(s8.c_str(),"1234567"));
245+
REQUIRE(!strcmp(s9.c_str(),"12345678"));
246+
REQUIRE(!strcmp(s15.c_str(),"12345678901234"));
247+
REQUIRE(!strcmp(s16.c_str(),"123456789012345"));
248+
REQUIRE(!strcmp(s17.c_str(),"1234567890123456"));
249+
s7 += '_';
250+
s8 += '_';
251+
s9 += '_';
252+
s15 += '_';
253+
s16 += '_';
254+
s17 += '_';
255+
REQUIRE(!strcmp(s7.c_str(),"123456_"));
256+
REQUIRE(!strcmp(s8.c_str(),"1234567_"));
257+
REQUIRE(!strcmp(s9.c_str(),"12345678_"));
258+
REQUIRE(!strcmp(s15.c_str(),"12345678901234_"));
259+
REQUIRE(!strcmp(s16.c_str(),"123456789012345_"));
260+
REQUIRE(!strcmp(s17.c_str(),"1234567890123456_"));
261+
}

0 commit comments

Comments
 (0)