diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c index cd48fa9ab..275dc34b8 100644 --- a/src/httpserver/new_http.c +++ b/src/httpserver/new_http.c @@ -440,13 +440,14 @@ int postany(http_request_t* request, const char* str, int len) { if (NULL == str) { // fd will be NULL for unit tests where HTTP packet is faked locally - if (request->fd != 0) { - if (request->replylen > 0) { - send(request->fd, request->reply, request->replylen, 0); - } - request->reply[0] = 0; - request->replylen = 0; + if (request->fd == 0) { + return request->replylen; } + if (request->replylen > 0) { + send(request->fd, request->reply, request->replylen, 0); + } + request->reply[0] = 0; + request->replylen = 0; return 0; } diff --git a/src/selftest/selftest_http.c b/src/selftest/selftest_http.c index a0a31c3e6..3d47e3f9c 100644 --- a/src/selftest/selftest_http.c +++ b/src/selftest/selftest_http.c @@ -2,6 +2,9 @@ #include "selftest_local.h" #include "../httpserver/new_http.h" +//#define JSMN_HEADER +///#include "../jsmn/jsmn.h" +#include "../cJSON/cJSON.h" // "GET /index?tgl=1 HTTP/1.1\r\n" const char *http_get_template1 = "GET /%s HTTP/1.1\r\n" @@ -21,6 +24,10 @@ const char *http_get_template1 = "GET /%s HTTP/1.1\r\n" "\r\n" "\r\n"; +//jsmn_parser parser; +cJSON *g_json; +cJSON *g_sec_power; + const char *Helper_GetPastHTTPHeader(const char *s) { while (*s) { if (!strncmp(s, "\r\n\r\n",4)) { @@ -30,12 +37,15 @@ const char *Helper_GetPastHTTPHeader(const char *s) { } return 0; } + static char outbuf[8192]; static char buffer[8192]; +static const char *replyAt; +//static jsmntok_t tokens[256]; /* We expect no more than qq JSON tokens */ + void Test_FakeHTTPClientPacket(const char *tg) { int iResult; int len; - const char *replyAt; http_request_t request; @@ -57,22 +67,272 @@ void Test_FakeHTTPClientPacket(const char *tg) { printf("Test_FakeHTTPClientPacket fake bytes sent: %d \n", iResult); len = HTTP_ProcessPacket(&request); + outbuf[request.replylen] = 0; printf("Test_FakeHTTPClientPacket fake bytes received: %d \n", len); replyAt = Helper_GetPastHTTPHeader(outbuf); } -void Test_Http() { +void Test_FakeHTTPClientPacket_JSON(const char *tg) { + int r; + Test_FakeHTTPClientPacket(tg); + + //jsmn_init(&parser); + //r = jsmn_parse(&parser, replyAt, strlen(replyAt), tokens, 256); + + if (g_json) { + cJSON_Delete(g_json); + } + g_json = cJSON_Parse(replyAt); + g_sec_power = cJSON_GetObjectItemCaseSensitive(g_json, "POWER"); +} +cJSON *Test_GetJSONValue_Generic(const char *keyword, const char *obj) { + cJSON *tmp; + cJSON *parent; + if (obj == 0 || obj[0] == 0) { + parent = g_json; + } + else { + parent = cJSON_GetObjectItemCaseSensitive(g_json, obj); + } + if (parent == 0) + return 0; + tmp = cJSON_GetObjectItemCaseSensitive(parent, keyword); + if (tmp == 0) + return 0; + return tmp; +} +const char *Test_GetJSONValue_Integer(const char *keyword, const char *obj) { + cJSON *tmp; + tmp = Test_GetJSONValue_Generic(keyword, obj); + if (tmp == 0) { + return -999999; + } + printf("Test_GetJSONValue_Integer will return %i for %s\n", tmp->valueint, keyword); + return tmp->valueint; +} +const char *Test_GetJSONValue_String(const char *keyword, const char *obj) { + cJSON *tmp; + tmp = Test_GetJSONValue_Generic(keyword, obj); + if (tmp == 0) { + return ""; + } + printf("Test_GetJSONValue_String will return %s for %s\n", tmp->valuestring, keyword); + return tmp->valuestring; +} + +void Test_Http_SingleRelayOnChannel1() { CMD_ExecuteCommand("clearAll", 0); + PIN_SetPinRoleForPinIndex(9, IOR_Relay); + PIN_SetPinChannelForPinIndex(9, 1); + + Test_FakeHTTPClientPacket_JSON("cm?cmnd=POWER"); + SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "OFF"); Test_FakeHTTPClientPacket("index?tgl=1"); - Test_FakeHTTPClientPacket("cm?cmnd=POWER"); + // read power + Test_FakeHTTPClientPacket_JSON("cm?cmnd=POWER"); + SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "ON"); - Test_FakeHTTPClientPacket("cm?cmnd=STATUS"); + // set power ON + Test_FakeHTTPClientPacket_JSON("cm?cmnd=POWER%20ON"); + SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "ON"); + + // set power OFF + Test_FakeHTTPClientPacket_JSON("cm?cmnd=POWER%20OFF"); + SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "OFF"); + + // set power OFF + Test_FakeHTTPClientPacket_JSON("cm?cmnd=POWER%20OFF"); + SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "OFF"); + + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0); + + // set power ON + Test_FakeHTTPClientPacket_JSON("cm?cmnd=POWER%20ON"); + SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "ON"); + + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 1); + +} +void Test_Http_TwoRelays() { + + CMD_ExecuteCommand("clearAll", 0); + PIN_SetPinRoleForPinIndex(9, IOR_Relay); + PIN_SetPinChannelForPinIndex(9, 1); + + PIN_SetPinRoleForPinIndex(10, IOR_Relay); + PIN_SetPinChannelForPinIndex(10, 2); + + // Channel 1 Off + // Channel 2 Off + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0); + + Test_FakeHTTPClientPacket("index?tgl=1"); + + // Channel 1 On + // Channel 2 Off + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0b1); + + Test_FakeHTTPClientPacket("index?tgl=2"); + // Channel 1 On + // Channel 2 On + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0b11); + Test_FakeHTTPClientPacket("index?tgl=1"); + // Channel 1 Off + // Channel 2 On + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0b10); +} +void Test_Http_FourRelays() { + + CMD_ExecuteCommand("clearAll", 0); + PIN_SetPinRoleForPinIndex(9, IOR_Relay); + PIN_SetPinChannelForPinIndex(9, 1); + + PIN_SetPinRoleForPinIndex(10, IOR_Relay); + PIN_SetPinChannelForPinIndex(10, 2); + + PIN_SetPinRoleForPinIndex(11, IOR_Relay); + PIN_SetPinChannelForPinIndex(11, 3); + + PIN_SetPinRoleForPinIndex(12, IOR_Relay); + PIN_SetPinChannelForPinIndex(12, 4); + + // Channel 1 Off + // Channel 2 Off + // Channel 3 Off + // Channel 4 Off + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0); + + Test_FakeHTTPClientPacket("index?tgl=3"); + + // Channel 1 Off + // Channel 2 Off + // Channel 3 On + // Channel 4 Off + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0b0100); + + Test_FakeHTTPClientPacket("index?tgl=2"); + // Channel 1 Off + // Channel 2 On + // Channel 3 On + // Channel 4 Off + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0b0110); + + + Test_FakeHTTPClientPacket("index?tgl=4"); + // Channel 1 Off + // Channel 2 On + // Channel 3 On + // Channel 4 On + // In STATUS register, power is encoded as integer... + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("Status", "Power", 0b1110); +} +/* +StatusSTS sample from Tasmota: + + "StatusSTS":{ + "Time":"2022-11-17T09:35:58", + "Uptime":"5T11:36:54", + "UptimeSec":473814, + "Heap":24, + "SleepMode":"Dynamic", + "Sleep":10, + "LoadAvg":99, + "MqttCount":3, + "POWER":"ON", + "Dimmer":80, + "Color":"144,114,204", + "HSBColor":"260,44,80", + "Channel":[ + 57, + 45, + 80 + ], + "Scheme":0, + "Fade":"OFF", + "Speed":1, + "LedTable":"ON", + "Wifi":{ + "AP":1, + "SSId":"DLINK_FastNet", + "BSSId":"30:B5:C2:5D:70:72", + "Channel":11, + "Mode":"11n", + "RSSI":54, + "Signal":-73, + "LinkCount":1, + "Downtime":"0T00:00:03" + } + } + +*/ +void Test_Http_LED_SingleChannel() { + + CMD_ExecuteCommand("clearAll", 0); + PIN_SetPinRoleForPinIndex(24, IOR_PWM); + PIN_SetPinChannelForPinIndex(24, 1); + + CMD_ExecuteCommand("led_enableAll 1", 0); + CMD_ExecuteCommand("led_dimmer 100", 0); + + // StatusSTS contains POWER and Dimmer + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("StatusSTS", "Dimmer", 100); + SELFTEST_ASSERT_JSON_VALUE_STRING("StatusSTS", "POWER", "ON"); + + CMD_ExecuteCommand("led_enableAll 0", 0); + // StatusSTS contains POWER and Dimmer + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("StatusSTS", "Dimmer", 100); + SELFTEST_ASSERT_JSON_VALUE_STRING("StatusSTS", "POWER", "OFF"); + + CMD_ExecuteCommand("led_dimmer 61", 0); + // StatusSTS contains POWER and Dimmer + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("StatusSTS", "Dimmer", 61); + SELFTEST_ASSERT_JSON_VALUE_STRING("StatusSTS", "POWER", "OFF"); + + + CMD_ExecuteCommand("led_enableAll 1", 0); + // StatusSTS contains POWER and Dimmer + Test_FakeHTTPClientPacket_JSON("cm?cmnd=STATUS"); + SELFTEST_ASSERT_JSON_VALUE_INTEGER("StatusSTS", "Dimmer", 61); + SELFTEST_ASSERT_JSON_VALUE_STRING("StatusSTS", "POWER", "ON"); + + + +} +void Test_Http() { + Test_Http_SingleRelayOnChannel1(); + Test_Http_TwoRelays(); + Test_Http_FourRelays(); + + + Test_Http_LED_SingleChannel(); } diff --git a/src/selftest/selftest_local.h b/src/selftest/selftest_local.h index 6dbf2b3f1..2b5b61734 100644 --- a/src/selftest/selftest_local.h +++ b/src/selftest/selftest_local.h @@ -17,6 +17,8 @@ void SelfTest_Failed(const char *file, int line, const char *exp); #define SELFTEST_ASSERT_ARGUMENT(argumentIndex, res) SELFTEST_ASSERT(!strcmp(Tokenizer_GetArg(argumentIndex), res)); #define SELFTEST_ASSERT_ARGUMENT_INTEGER(argumentIndex, res) SELFTEST_ASSERT((Tokenizer_GetArgInteger(argumentIndex)== res)); #define SELFTEST_ASSERT_ARGUMENTS_COUNT(wantedCount) SELFTEST_ASSERT((Tokenizer_GetArgsCount()==wantedCount)); +#define SELFTEST_ASSERT_JSON_VALUE_STRING(obj, varName, res) SELFTEST_ASSERT(!strcmp(Test_GetJSONValue_String(varName,obj), res)); +#define SELFTEST_ASSERT_JSON_VALUE_INTEGER(obj, varName, res) SELFTEST_ASSERT((Test_GetJSONValue_Integer(varName,obj) == res)); //#define FLOAT_EQUALS (a,b) (abs(a-b)<0.001f) inline bool Float_Equals(float a, float b) {