From 56e754eeb7b0def63f783ba4bd6cc61128934a04 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 10 Feb 2025 17:08:49 +0100 Subject: [PATCH 01/15] drivers/bestfortress.c: do not use whitespace in status_set() args [#2708] Signed-off-by: Jim Klimov --- drivers/bestfortress.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index 8869840c6f..f9aeab7982 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -35,7 +35,7 @@ #endif #define DRIVER_NAME "Best Fortress UPS driver" -#define DRIVER_VERSION "0.10" +#define DRIVER_VERSION "0.11" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -401,13 +401,13 @@ void upsdrv_updateinfo(void) status_init(); if (low_batt) - status_set("LB "); + status_set("LB"); else if (trimming) status_set("TRIM"); else if (boosting) status_set("BOOST"); else - status_set(is_online ? (is_off ? "OFF " : "OL ") : "OB "); + status_set(is_online ? (is_off ? "OFF" : "OL") : "OB"); /* setinfo(INFO_STATUS, "%s%s", * (util < lownorm) ? "BOOST ", "", From 225d12b47dc24f2243031a08e7c426d7afabe4b9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 10 Feb 2025 17:16:09 +0100 Subject: [PATCH 02/15] drivers/liebert-gxe.c: do not use whitespace in status_set() args [#2708] Signed-off-by: Jim Klimov --- drivers/liebert-gxe.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/liebert-gxe.c b/drivers/liebert-gxe.c index 36886c80f8..dbed3f149a 100644 --- a/drivers/liebert-gxe.c +++ b/drivers/liebert-gxe.c @@ -24,7 +24,7 @@ #include "ydn23.h" #define DRIVER_NAME "Liebert GXE Series UPS driver" -#define DRIVER_VERSION "0.02" +#define DRIVER_VERSION "0.03" #define PROBE_RETRIES 3 #define DEFAULT_STALE_RETRIES 3 @@ -173,9 +173,10 @@ static void upsdrv_updateinfo_onoff(void) status_set("OB"); else if (pwrval == 0x01) status_set("OL"); - else if (pwrval == 0x02) - status_set("OL BYPASS"); - else + else if (pwrval == 0x02) { + status_set("OL"); + status_set("BYPASS"); + } else upslogx(LOG_WARNING, "unknown ups state: %x %x", (unsigned int)pwrval, (unsigned int)rectval); From 472eac5bb59db72d9982a6f033cf76f151230af8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 10 Feb 2025 17:43:09 +0100 Subject: [PATCH 03/15] tests/generic_gpio_utest.c: piggy-back to test for duplicates with status_set() [#2708] Signed-off-by: Jim Klimov --- tests/generic_gpio_utest.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 3c171672df..5f732da463 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -143,6 +143,7 @@ int main(int argc, char **argv) { char testDescFileNameBuf[LARGEBUF]; char *testDescFileName = "generic_gpio_test.txt"; unsigned int i; + const char *valueStr = NULL; test_with_exit=0; @@ -384,6 +385,26 @@ int main(int argc, char **argv) { } } + /* FIXME: Standalone test with driver-program dependencies? */ + status_init(); + nut_debug_level = 6; + status_set("OL"); + status_set("OL BOOST"); + status_set("OB"); + status_set("BOOST"); + status_commit(); + valueStr = dstate_getinfo("ups.status"); + nut_debug_level = 0; + if (!strcmp(valueStr, "OL BOOST OB")) { + printf("pass"); + cases_passed++; + } else { + printf("fail"); + cases_failed++; + } + i++; + printf(" test for ups.status: '%s'; any duplicates?\n", NUT_STRARG(valueStr)); + printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); fclose(testData); From d43377b95ffb1e8e9529443f82274b79f8bed54d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 10 Feb 2025 18:05:55 +0100 Subject: [PATCH 04/15] drivers/dstate.c: fix status_get(), got inverted maths in a check [#2565, #2708] Signed-off-by: Jim Klimov --- drivers/dstate.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/dstate.c b/drivers/dstate.c index f830ea8e6a..20692db767 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -1648,7 +1648,11 @@ int status_get(const char *buf) if (!s) return 0; - offset = status_buf - s; + offset = s - status_buf; +#if 0 + upsdebugx(3, "%s: '%s' in '%s': offset=%" PRIuSIZE" buflen=%" PRIuSIZE" s[buflen]='0x%2X'\n", + __func__, buf, status_buf, offset, buflen, s[buflen]); +#endif if (offset == 0 || status_buf[offset - 1] == ' ') { /* We have hit the start of token */ if (s[buflen] == '\0' || s[buflen] == ' ') { From cd95c9e79aa67ee0e9d8bcd047c9057794c0f695 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 10 Feb 2025 18:07:00 +0100 Subject: [PATCH 05/15] drivers/dstate.c, NEWS.adoc: status_set(): if we are reluctantly adding "A FEW TOKENS" at once, recurse to add one by one and so avoid duplicates [#2708] As a side effect, should also strip surrounding whitespace characters. Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++-- drivers/dstate.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index bad715de33..43965430d3 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -479,8 +479,8 @@ relocated into new `shutdown.default` INSTCMD definitions. [#2670] * custom `distcheck-something` targets did not inherit `DISTCHECK_FLAGS` properly. [#2541] * added `status_get()` in NUT driver state API, to check if a status - token string had been set recently, and to avoid duplicate settings. - [PR #2565] + token string had been set recently, and to avoid duplicate settings; + fixed `status_set()` for multi-token arguments. [PR #2565, issue #2708] * local socket/pipe protocol introduced a `LOGOUT` command for cleaner disconnection handling. [#2572] * codebase adapted to the liking of `clang-18` and newer revisions of diff --git a/drivers/dstate.c b/drivers/dstate.c index 20692db767..5664428c41 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -1668,6 +1668,39 @@ int status_get(const char *buf) /* add a status element */ void status_set(const char *buf) { +#if 0 + upsdebugx(3, "%s: '%s'\n", __func__, buf); +#endif + if (strstr(buf, " ")) { + /* Recurse adding each sub-status one by one (avoid duplicates) + * We frown upon adding "A FEW TOKENS" at once, but in e.g. + * snmp-ups subdrivers with a mapping table this is not easily + * avoidable... + */ + char *tmp = xstrdup(buf), *p = tmp, *s = tmp; + while (*p) { + if (*p == ' ') { + *p = '\0'; + if (s != p) { + /* Only recurse to set non-trivial tokens */ + status_set(s); + } + p++; + s = p; /* Start of new word... or a consecutive space to ignore on next cycle */ + } else { + p++; + } + } + + if (s != p) { + /* Last valid token did end with (*p=='\0') */ + status_set(s); + } + + free(tmp); + return; + } + if (ignorelb && !strcasecmp(buf, "LB")) { upsdebugx(2, "%s: ignoring LB flag from device", __func__); return; From 2d4f931b36694dbc0a4215e7c89afb2b17d37eba Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 10 Feb 2025 18:11:02 +0100 Subject: [PATCH 06/15] tests/generic_gpio_utest.c: check that whitespace chars around status_set() args are stripped [#2708] Signed-off-by: Jim Klimov --- tests/generic_gpio_utest.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 5f732da463..b7b94f47fb 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -388,10 +388,10 @@ int main(int argc, char **argv) { /* FIXME: Standalone test with driver-program dependencies? */ status_init(); nut_debug_level = 6; - status_set("OL"); + status_set(" OL "); status_set("OL BOOST"); - status_set("OB"); - status_set("BOOST"); + status_set("OB "); + status_set(" BOOST"); status_commit(); valueStr = dstate_getinfo("ups.status"); nut_debug_level = 0; From 6ecb7fede68097fe30ae17f23ac74c22b93d4e20 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 10 Feb 2025 20:27:56 +0100 Subject: [PATCH 07/15] docs/new-drivers.txt: describe in ups.status values also that/how ARALM can be added [#2708] Signed-off-by: Jim Klimov --- docs/new-drivers.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/new-drivers.txt b/docs/new-drivers.txt index 3ca3ca9c76..be88bb3503 100644 --- a/docs/new-drivers.txt +++ b/docs/new-drivers.txt @@ -247,6 +247,10 @@ Possible values for status_set: BOOST -- UPS is boosting incoming voltage FSD -- Forced Shutdown (restricted use, see the note below) +Internally, an `ALARM` value would be added (typically as first in the list) +if the `ups.alarm` is currently not empty. For more details, see below in +`alarm_set()` description. + Anything else will not be recognized by the usual clients expecting a particular NUT standard release. New tokens may appear over time, but driver developers should coordinate with the nut-upsdev list before creating From 853de1f26c3790029993e77a81a7523df5cd8713 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 06:05:57 +0100 Subject: [PATCH 08/15] appveyor.yml: ensure we can create version-less snapshot dir symlink The fault puzzled me though: we do pre-remove '.inst' whole... [00:36:07] CHECKING if any executable files were installed to locations other than those covered by this recipe, so might not have needed DLLs bundled near them [00:36:08] ln: ./.inst/NUT-for-Windows-x86_64-SNAPSHOT: cannot overwrite directory [00:36:08] Command exited with code 1 Signed-off-by: Jim Klimov --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b6d1a32c56..f37b854ea2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -110,7 +110,7 @@ after_test: set MSYSTEM=MINGW64 REM Oh the joys of shell scripting with strings passed through CMD: REM Note: currently Python installation path with MSYS is buggy [#1584] - C:\msys64\usr\bin\bash -lc 'date -u; set -e ; if ! rm -rf ".inst" ; then echo "WARNING: Failed to clean away .inst" ; fi ; PATH="/mingw64/lib/ccache/bin:/mingw64/bin:$PATH" make -s install-win-bundle DESTDIR="`pwd`/.inst/NUT-for-Windows-x86_64-SNAPSHOT-%APPVEYOR_BUILD_VERSION%" ; ln -fs "NUT-for-Windows-x86_64-SNAPSHOT-%APPVEYOR_BUILD_VERSION%" ./.inst/NUT-for-Windows-x86_64-SNAPSHOT ; ( cd .inst/NUT-for-Windows-x86_64-SNAPSHOT ; find . -ls ; ) ; date -u' + C:\msys64\usr\bin\bash -lc 'date -u; set -e ; if ! rm -rf ".inst" ; then echo "WARNING: Failed to clean away .inst" ; fi ; PATH="/mingw64/lib/ccache/bin:/mingw64/bin:$PATH" make -s install-win-bundle DESTDIR="`pwd`/.inst/NUT-for-Windows-x86_64-SNAPSHOT-%APPVEYOR_BUILD_VERSION%" ; rm -rf ./.inst/NUT-for-Windows-x86_64-SNAPSHOT || true ; ln -fs "NUT-for-Windows-x86_64-SNAPSHOT-%APPVEYOR_BUILD_VERSION%" ./.inst/NUT-for-Windows-x86_64-SNAPSHOT ; ( cd .inst/NUT-for-Windows-x86_64-SNAPSHOT ; find . -ls ; ) ; date -u' cd .inst 7z a ../NUT-for-Windows-x86_64-SNAPSHOT-%APPVEYOR_BUILD_VERSION%.7z NUT* - cmd: | From 6e9637e25e009d8dc63b9a4570fd45d267aa47e8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 06:44:42 +0100 Subject: [PATCH 09/15] Introduce tests/driver_methods_utest [#2708] Relocated code tried earlier in generic_gpio_utest.c (not as portable a container - far from everyone builds it) Signed-off-by: Jim Klimov --- tests/.gitignore | 3 ++ tests/Makefile.am | 5 ++ tests/driver_methods_utest.c | 90 ++++++++++++++++++++++++++++++++++++ tests/generic_gpio_utest.c | 21 --------- 4 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 tests/driver_methods_utest.c diff --git a/tests/.gitignore b/tests/.gitignore index ab9969c713..59edbae1af 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -4,6 +4,9 @@ /cppnit /cppnit.log /cppnit.trs +/driver_methods_utest +/driver_methods_utest.log +/driver_methods_utest.trs /gpiotest /gpiotest.log /gpiotest.trs diff --git a/tests/Makefile.am b/tests/Makefile.am index 38b4f71c99..5d30b5c8de 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -116,6 +116,11 @@ endif !WITH_GPIO CLEANFILES += generic_gpio_libgpiod.c generic_gpio_common.c EXTRA_DIST += generic_gpio_utest.h generic_gpio_test.txt +TESTS += driver_methods_utest +driver_methods_utest_SOURCES = driver_methods_utest.c +driver_methods_utest_LDADD = $(top_builddir)/drivers/libdummy_mockdrv.la +driver_methods_utest_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/tests -DDRIVERS_MAIN_WITHOUT_MAIN=1 + # Make sure out-of-dir dependencies exist (especially when dev-building parts): $(top_builddir)/drivers/libdummy_mockdrv.la \ $(top_builddir)/common/libnutconf.la \ diff --git a/tests/driver_methods_utest.c b/tests/driver_methods_utest.c new file mode 100644 index 0000000000..454f15c7ef --- /dev/null +++ b/tests/driver_methods_utest.c @@ -0,0 +1,90 @@ +/* driver_methods_utest.c - NUT driver code test tool + * + * Copyright (C) + * 2025 Jim Klimov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "config.h" +#include "main.h" +#include "dstate.h" +#include "attribute.h" +#include "nut_stdint.h" + +/* driver version */ +#define DRIVER_NAME "Mock driver for unit tests" +#define DRIVER_VERSION "0.01" + +/* driver description structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "Jim Klimov ", + DRV_EXPERIMENTAL, + { NULL } +}; + +static int cases_passed = 0; +static int cases_failed = 0; + +static char * pass_fail[2] = {"pass", "fail"}; + +void upsdrv_cleanup(void) {} +void upsdrv_shutdown(void) {} + +int main(int argc, char **argv) { + const char *valueStr = NULL; + + NUT_UNUSED_VARIABLE(argc); + NUT_UNUSED_VARIABLE(argv); + + cases_passed = 0; + cases_failed = 0; + + /* test case #1 */ + status_init(); + nut_debug_level = 6; + status_set(" OL "); + status_set("OL BOOST"); + status_set("OB "); + status_set(" BOOST"); + status_commit(); + valueStr = dstate_getinfo("ups.status"); + nut_debug_level = 0; + if (!strcmp(valueStr, "OL BOOST OB")) { + printf("%s", pass_fail[0]); + cases_passed++; + } else { + printf("%s", pass_fail[1]); + cases_failed++; + } + printf(" test for ups.status: '%s'; any duplicates?\n", NUT_STRARG(valueStr)); + + /* finish */ + printf("test_rules completed. Total cases %d, passed %d, failed %d\n", + cases_passed+cases_failed, cases_passed, cases_failed); + + dstate_free(); + upsdrv_cleanup(); + + /* Return 0 (exit-code OK, boolean false) if no tests failed and some ran */ + if ( (cases_failed == 0) && (cases_passed > 0) ) + return 0; + + return 1; +} diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index b7b94f47fb..3c171672df 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -143,7 +143,6 @@ int main(int argc, char **argv) { char testDescFileNameBuf[LARGEBUF]; char *testDescFileName = "generic_gpio_test.txt"; unsigned int i; - const char *valueStr = NULL; test_with_exit=0; @@ -385,26 +384,6 @@ int main(int argc, char **argv) { } } - /* FIXME: Standalone test with driver-program dependencies? */ - status_init(); - nut_debug_level = 6; - status_set(" OL "); - status_set("OL BOOST"); - status_set("OB "); - status_set(" BOOST"); - status_commit(); - valueStr = dstate_getinfo("ups.status"); - nut_debug_level = 0; - if (!strcmp(valueStr, "OL BOOST OB")) { - printf("pass"); - cases_passed++; - } else { - printf("fail"); - cases_failed++; - } - i++; - printf(" test for ups.status: '%s'; any duplicates?\n", NUT_STRARG(valueStr)); - printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); fclose(testData); From 3d683740eb97c5aecb1ee489f7e34480b4e998e4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 07:09:08 +0100 Subject: [PATCH 10/15] tests/driver_methods_utest.c: refactor pass.fail reporting [#2708] Signed-off-by: Jim Klimov --- tests/driver_methods_utest.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tests/driver_methods_utest.c b/tests/driver_methods_utest.c index 454f15c7ef..521f34f731 100644 --- a/tests/driver_methods_utest.c +++ b/tests/driver_methods_utest.c @@ -47,6 +47,24 @@ static char * pass_fail[2] = {"pass", "fail"}; void upsdrv_cleanup(void) {} void upsdrv_shutdown(void) {} +static void report_pass(void) { + printf("%s", pass_fail[0]); + cases_passed++; +} + +static void report_fail(void) { + printf("%s", pass_fail[1]); + cases_failed++; +} + +static int report_0_means_pass(int i) { + if (i == 0) { + report_pass(); + } else { + report_fail(); + } + return i; +} int main(int argc, char **argv) { const char *valueStr = NULL; @@ -66,13 +84,7 @@ int main(int argc, char **argv) { status_commit(); valueStr = dstate_getinfo("ups.status"); nut_debug_level = 0; - if (!strcmp(valueStr, "OL BOOST OB")) { - printf("%s", pass_fail[0]); - cases_passed++; - } else { - printf("%s", pass_fail[1]); - cases_failed++; - } + report_0_means_pass(strcmp(valueStr, "OL BOOST OB")); printf(" test for ups.status: '%s'; any duplicates?\n", NUT_STRARG(valueStr)); /* finish */ From 053bef889165c0f15d2ab73dc338346ff7a1126e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 07:10:34 +0100 Subject: [PATCH 11/15] tests/driver_methods_utest.c: test ALARM status [#2708] Signed-off-by: Jim Klimov --- tests/driver_methods_utest.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/driver_methods_utest.c b/tests/driver_methods_utest.c index 521f34f731..30a09396f5 100644 --- a/tests/driver_methods_utest.c +++ b/tests/driver_methods_utest.c @@ -87,6 +87,17 @@ int main(int argc, char **argv) { report_0_means_pass(strcmp(valueStr, "OL BOOST OB")); printf(" test for ups.status: '%s'; any duplicates?\n", NUT_STRARG(valueStr)); + /* test case #2, build on top of #1 */ + alarm_init(); + alarm_set("Test alarm 1"); + alarm_set("Test alarm 2"); + alarm_commit(); + /* Note: normally we re-init and re-set the values */ + status_commit(); + valueStr = dstate_getinfo("ups.status"); + report_0_means_pass(strcmp(valueStr, "ALARM OL BOOST OB")); + printf(" test for ups.status: '%s'; got alarm?\n", NUT_STRARG(valueStr)); + /* finish */ printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); From 9ec4b82ddde0e2d7f9d00e9774c5d4569f2dfbca Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 07:18:48 +0100 Subject: [PATCH 12/15] tests/driver_methods_utest.c: test ALARM contents (with dupes) [#2708] Signed-off-by: Jim Klimov --- tests/driver_methods_utest.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/driver_methods_utest.c b/tests/driver_methods_utest.c index 30a09396f5..2f1e27916a 100644 --- a/tests/driver_methods_utest.c +++ b/tests/driver_methods_utest.c @@ -91,6 +91,7 @@ int main(int argc, char **argv) { alarm_init(); alarm_set("Test alarm 1"); alarm_set("Test alarm 2"); + alarm_set("Test alarm 1"); alarm_commit(); /* Note: normally we re-init and re-set the values */ status_commit(); @@ -98,6 +99,12 @@ int main(int argc, char **argv) { report_0_means_pass(strcmp(valueStr, "ALARM OL BOOST OB")); printf(" test for ups.status: '%s'; got alarm?\n", NUT_STRARG(valueStr)); + /* test case #3, build on top of #2 */ + valueStr = dstate_getinfo("ups.alarm"); + /* NOTE: no dedup here! */ + report_0_means_pass(strcmp(valueStr, "Test alarm 1 Test alarm 2 Test alarm 1")); + printf(" test for ups.alarm: '%s'; got 3 alarms?\n", NUT_STRARG(valueStr)); + /* finish */ printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); From 741663362faeeee193450c1f22e7eb285a7fd12d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 07:19:53 +0100 Subject: [PATCH 13/15] tests/driver_methods_utest.c: test ups.status sub-token detection [#2708] Signed-off-by: Jim Klimov --- tests/driver_methods_utest.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/driver_methods_utest.c b/tests/driver_methods_utest.c index 2f1e27916a..77da6c2221 100644 --- a/tests/driver_methods_utest.c +++ b/tests/driver_methods_utest.c @@ -105,6 +105,20 @@ int main(int argc, char **argv) { report_0_means_pass(strcmp(valueStr, "Test alarm 1 Test alarm 2 Test alarm 1")); printf(" test for ups.alarm: '%s'; got 3 alarms?\n", NUT_STRARG(valueStr)); + /* test case #4, build on top of #1 and #2 */ + /* Note: normally we re-init and re-set the values */ + status_set("BOO"); + status_set("BOO"); + status_set("OST"); + status_set("OST"); + status_set("OOS"); + status_set("OOS"); + status_commit(); + valueStr = dstate_getinfo("ups.status"); + nut_debug_level = 0; + report_0_means_pass(strcmp(valueStr, "ALARM OL BOOST OB BOO OST OOS")); + printf(" test for ups.status: '%s'; any duplicates?\n", NUT_STRARG(valueStr)); + /* finish */ printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); From 332cd9e483548388c8ed86dead53d064a4eed505 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 07:31:40 +0100 Subject: [PATCH 14/15] drivers/dstate.c: status_get(): properly handle tokens that are substrings of another [#2708, #2565] Signed-off-by: Jim Klimov --- drivers/dstate.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/dstate.c b/drivers/dstate.c index 5664428c41..91baf88656 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -1644,8 +1644,9 @@ int status_get(const char *buf) s = strstr(status_buf, buf); buflen = strlen(buf); - /* not found */ - if (!s) +repeat: + /* not found or hit end of line */ + if (!s || !*s) return 0; offset = s - status_buf; @@ -1662,7 +1663,8 @@ int status_get(const char *buf) } /* buf was a substring of some other token */ - return 0; + s = strstr(s + 1, buf); + goto repeat; } /* add a status element */ From b529f0bac0815aa7fa2baa9e761199924d908308 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 11 Feb 2025 17:55:43 +0100 Subject: [PATCH 15/15] drivers/main.c: avoid declaring "mutex" in WIN32 builds without main() for test mocks [#2708] Signed-off-by: Jim Klimov --- drivers/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/main.c b/drivers/main.c index 0217e5438a..78339d7f92 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -47,9 +47,11 @@ const char *progname = NULL, *upsname = NULL, *device_name = NULL; /* may be set by the driver to wake up while in dstate_poll_fds */ TYPE_FD extrafd = ERROR_FD; -#ifdef WIN32 +#ifndef DRIVERS_MAIN_WITHOUT_MAIN +# ifdef WIN32 static HANDLE mutex = INVALID_HANDLE_VALUE; -#endif +# endif /* WIN32 */ +#endif /* DRIVERS_MAIN_WITHOUT_MAIN */ /* Set by INSTCMD to killpower or by running `drivername -k` to * help differentiate calls into upsdrv_shutdown() and further