Skip to content

Commit 273b0d2

Browse files
committed
Test & bugfixing:
Processing * in test environment -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Building & Uploading... Testing... If you don't see any output for the first 10 secs, please reset board (press reset button) test/basictest.cpp:172: test_int_config [PASSED] test/basictest.cpp:174: test_bool_config [PASSED] test/basictest.cpp:176: test_string_config [PASSED] test/basictest.cpp:178: test_float_config [PASSED] test/basictest.cpp:180: test_password_masking [PASSED] test/basictest.cpp:182: test_callback_function [PASSED] test/basictest.cpp:185: test_key_too_long_exception [PASSED] test/basictest.cpp:187: test_key_truncation_warning [PASSED] test/basictest.cpp:189: test_logger_callback [PASSED] test/basictest.cpp:191: test_ap_mode_initialization [PASSED] test/basictest.cpp:193: test_sta_mode_initialization [PASSED] ------------------------------------------------------------------------------------------- test:* [PASSED] Took 35.93 seconds ------------------------------------------------------------------------------------------- ======================================================================================================== SUMMARY ======================================================================================================== Environment Test Status Duration ------------- ------ -------- ------------ nodemcu-32s * PASSED 00:00:50.214 test * PASSED 00:00:35.926 ====================================================================================== 22 test cases: 22 succeeded in 00:01:26.140 ====================================================================================== Changes to be committed: new file: .github/workflows/pio-tests.yml modified: examples/html/html-maker.html modified: platformio.ini modified: src/ConfigManager.h modified: src/html_content.h modified: src/main.cpp modified: test/basictest.cpp
1 parent 4264f24 commit 273b0d2

File tree

7 files changed

+254
-126
lines changed

7 files changed

+254
-126
lines changed

.github/workflows/pio-tests.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: PlatformIO-Tests
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
run-tests:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout Code
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: "3.10"
21+
22+
- name: Install PlatformIO Core
23+
run: |
24+
pip install -U platformio
25+
26+
- name: Run PlatformIO Tests
27+
run: |
28+
pio test -e test

examples/html/html-maker.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<style>
77
body {
88
font-family: Arial, sans-serif;
9-
margin: 20px;
9+
margin: 2rem;
1010
background-color: #f0f0f0;
1111
}
1212
.category {
@@ -228,7 +228,7 @@ <h1>Device Configuration</h1>
228228
});
229229

230230
try {
231-
const response = await fetch("/save", {
231+
const response = await fetch("/config/save_all", {
232232
method: "POST",
233233
headers: { "Content-Type": "application/json" },
234234
body: JSON.stringify(config),
@@ -254,13 +254,13 @@ <h1>Device Configuration</h1>
254254
});
255255

256256
try {
257-
const response = await fetch("/apply", {
257+
const response = await fetch("/config/apply_all", {
258258
method: "POST",
259259
headers: { "Content-Type": "application/json" },
260260
body: JSON.stringify(config),
261261
});
262262
showStatus(
263-
response.ok ? "All settings Applyed!" : "Error!",
263+
response.ok ? "All settings Applied!" : "Error!",
264264
response.ok ? "green" : "red"
265265
);
266266
} catch (error) {
@@ -283,7 +283,7 @@ <h1>Device Configuration</h1>
283283

284284
function rebootDevice() {
285285
if (!confirm("Reboot device?")) return;
286-
fetch("/reboot", { method: "POST" })
286+
fetch("/config/reboot", { method: "POST" })
287287
.then((response) =>
288288
response.ok ? showStatus("Rebooting...", "blue") : null
289289
)

platformio.ini

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,31 @@ build_unflags = -std=gnu++11
1818
build_flags =
1919
-Wno-deprecated-declarations
2020
-std=gnu++17
21-
lib_deps = bblanchon/ArduinoJson@^7.4.1
21+
-DUNIT_TEST
22+
lib_deps =
23+
bblanchon/ArduinoJson@^7.4.1
24+
throwtheswitch/Unity@^2.6.0
2225

26+
test_ignore =
27+
src/main.cpp
2328

2429
[platformio]
2530
description = esp32 c++ V17 Project for manage settings
2631

32+
[env:test]
33+
platform = espressif32
34+
board = nodemcu-32s
35+
framework = arduino
36+
monitor_speed = 115200
37+
upload_port = COM[3]
38+
build_unflags = -std=gnu++11
39+
build_flags =
40+
-Wno-deprecated-declarations
41+
-std=gnu++17
42+
-DUNIT_TEST
43+
lib_deps =
44+
bblanchon/ArduinoJson@^7.4.1
45+
throwtheswitch/Unity@^2.6.0
46+
47+
test_ignore =
48+
src/main.cpp

src/ConfigManager.h

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ class NonFatalException : public std::exception {
4343
public:
4444
NonFatalException(const std::string& msg) : message(msg) {
4545
//todo: add a logger, or something like that
46-
// log_message("[WARN] %s", msg );
46+
String logMsg = "[WARN] " + String(msg.c_str());
47+
// if (!Serial) {
48+
// Serial.begin(115200);
49+
// while (!Serial); // Warte auf Verbindung
50+
// }
51+
// Serial.println(logMsg);
52+
// Serial.flush();
4753
}
4854
const char* what() const noexcept override {
4955
return message.c_str();
@@ -93,41 +99,25 @@ class BaseSetting {
9399
virtual bool fromJSON(const JsonVariant &value) = 0;
94100

95101
const char* getKey() const {
96-
static char key[16]; // 15 chars + Null-Terminator
97-
const int MAX_CATEGORY_LENGTH = 13; // Max for Category (14 - 1 for '_' - 1 Min Name)
102+
static char key[64]; // 15 chars + Null-Terminator
103+
const int MAX_CATEGORY_LENGTH = 13;
98104
const int MAX_TOTAL_LENGTH = 15;
99105

100-
// Cut the Category (WebUI all same)
101-
char categoryTrimmed[MAX_CATEGORY_LENGTH + 1];
102-
strncpy(categoryTrimmed, category, MAX_CATEGORY_LENGTH);
103-
categoryTrimmed[MAX_CATEGORY_LENGTH] = '\0';
104-
105-
// throw exception if category is too long
106106
if (strlen(category) > MAX_CATEGORY_LENGTH) {
107107
throw KeyTooLongException(category, name);
108108
}
109109

110-
// get length of the max name
111-
int maxNameLength = MAX_TOTAL_LENGTH - strlen(categoryTrimmed) - 1;
112-
113-
// cut the name, but mot less than 1 char
110+
int maxNameLength = MAX_TOTAL_LENGTH - strlen(category) - 1;
111+
114112
char nameTrimmed[maxNameLength + 1];
115113
strncpy(nameTrimmed, name, maxNameLength);
116114
nameTrimmed[maxNameLength] = '\0';
117115

118-
snprintf(key, sizeof(key), "%s_%s", categoryTrimmed, nameTrimmed);
119-
120-
// if name is truncated
121-
int max_name_len = MAX_TOTAL_LENGTH - strlen(category) - 1;
122-
if(strlen(name) > max_name_len) {
123-
char trimmed_name[max_name_len + 1];
124-
strncpy(trimmed_name, name, max_name_len);
125-
trimmed_name[max_name_len] = '\0';
126-
127-
snprintf(key, sizeof(key), "%s_%s", category, trimmed_name);
128-
throw KeyTruncatedWarning(key, trimmed_name);
116+
if (strlen(name) > maxNameLength) {
117+
throw KeyTruncatedWarning(name, nameTrimmed);
129118
}
130119

120+
snprintf(key, sizeof(key), "%s_%s", category, nameTrimmed);
131121
return key;
132122
}
133123

@@ -353,6 +343,7 @@ class ConfigManagerClass {
353343
WiFi.config(ip, gateway, subnet);
354344

355345
log_message("🔌 Connecting to WiFi SSID: %s\n", ssid.c_str());
346+
WiFi.mode(WIFI_STA); // Set WiFi mode to Station bugfix for unit test
356347
WiFi.begin(ssid.c_str(), password.c_str());
357348

358349
unsigned long startAttemptTime = millis();
@@ -381,6 +372,7 @@ class ConfigManagerClass {
381372

382373
void startWebServer(const String &ssid, const String &password) {
383374
log_message("🌐 DHCP mode active - Connecting to WiFi...");
375+
WiFi.mode(WIFI_STA); // Set WiFi mode to Station bugfix for unit test
384376
WiFi.begin(ssid.c_str(), password.c_str());
385377

386378
unsigned long startAttemptTime = millis();
@@ -426,7 +418,7 @@ class ConfigManagerClass {
426418
for (auto *s : settings) {
427419
if (String(s->getCategory()) == category && String(s->getName()) == key) {
428420
if (s->fromJSON(doc["value"])) {
429-
log_message("✅ Setting applied");
421+
log_message("✅ Setting applied Category: %s, Key: %s", category.c_str(), key.c_str());
430422
server.send(200, "application/json", "{\"status\":\"applied\"}");
431423
return;
432424
}
@@ -437,6 +429,17 @@ class ConfigManagerClass {
437429
server.send(404, "application/json", "{\"status\":\"not_found\"}");
438430
});
439431

432+
server.on("/config/apply_all", HTTP_POST, [this]() {
433+
DynamicJsonDocument doc(1024);
434+
log_message("🌐 Applying all settings...");
435+
deserializeJson(doc, server.arg("plain"));
436+
if (fromJSON(doc)) {
437+
server.send(200, "application/json", "{\"status\":\"applied\"}");
438+
} else {
439+
server.send(400, "application/json", "{\"status\":\"invalid\"}");
440+
}
441+
});
442+
440443
// Save single setting
441444
server.on("/config/save", HTTP_POST, [this]() {
442445
String category = server.arg("category");
@@ -453,19 +456,19 @@ class ConfigManagerClass {
453456
prefs.begin("config", false);
454457
s->save(prefs);
455458
prefs.end();
456-
log_message("✅ Setting saved");
459+
log_message("✅ Setting saved Category: %s, Key: %s", category.c_str(), key.c_str());
457460
server.send(200, "application/json", "{\"status\":\"saved\"}");
458461
return;
459462
}
460463
}
461464
}
462465

463-
log_message("❌ Setting not found");
466+
log_message("❌ Setting not found category: %s, key: %s", category.c_str(), key.c_str());
464467
server.send(404, "application/json", "{\"status\":\"not_found\"}");
465468
});
466469

467470
// Reboot
468-
server.on("/reboot", HTTP_POST, [this]() {
471+
server.on("/config/reboot", HTTP_POST, [this]() {
469472
server.send(200, "application/json", "{\"status\":\"rebooting\"}");
470473
log_message("🔄 Device rebooting...");
471474
delay(100);
@@ -478,7 +481,7 @@ class ConfigManagerClass {
478481
});
479482

480483
// Save all settings
481-
server.on("/save", HTTP_POST, [this]() {
484+
server.on("/config/save_all", HTTP_POST, [this]() {
482485
DynamicJsonDocument doc(1024);
483486
log_message("🌐 Saving all settings...");
484487
deserializeJson(doc, server.arg("plain"));
@@ -559,6 +562,10 @@ class ConfigManagerClass {
559562
logger(buffer);
560563
}
561564

565+
void triggerLoggerTest() {
566+
log_message("Test message abcdefghijklmnop");
567+
}
568+
562569
private:
563570
Preferences prefs;
564571
std::vector<BaseSetting *> settings;

src/html_content.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const char WEB_HTML[] PROGMEM = R"rawliteral(
1212
<style>
1313
body {
1414
font-family: Arial, sans-serif;
15-
margin: 20px;
15+
margin: 2rem;
1616
background-color: #f0f0f0;
1717
}
1818
.category {
@@ -234,7 +234,7 @@ const char WEB_HTML[] PROGMEM = R"rawliteral(
234234
});
235235
236236
try {
237-
const response = await fetch("/save", {
237+
const response = await fetch("/config/save_all", {
238238
method: "POST",
239239
headers: { "Content-Type": "application/json" },
240240
body: JSON.stringify(config),
@@ -260,13 +260,13 @@ const char WEB_HTML[] PROGMEM = R"rawliteral(
260260
});
261261
262262
try {
263-
const response = await fetch("/apply", {
263+
const response = await fetch("/config/apply_all", {
264264
method: "POST",
265265
headers: { "Content-Type": "application/json" },
266266
body: JSON.stringify(config),
267267
});
268268
showStatus(
269-
response.ok ? "All settings Applyed!" : "Error!",
269+
response.ok ? "All settings Applied!" : "Error!",
270270
response.ok ? "green" : "red"
271271
);
272272
} catch (error) {
@@ -289,7 +289,7 @@ const char WEB_HTML[] PROGMEM = R"rawliteral(
289289
290290
function rebootDevice() {
291291
if (!confirm("Reboot device?")) return;
292-
fetch("/reboot", { method: "POST" })
292+
fetch("/config/reboot", { method: "POST" })
293293
.then((response) =>
294294
response.ok ? showStatus("Rebooting...", "blue") : null
295295
)

0 commit comments

Comments
 (0)