"""Exercise actual MQTT diagnostic callbacks without a broker or credentials.""" from pathlib import Path import subprocess root = Path(__file__).resolve().parents[1] output = root / 'artifacts/wss/new-board/mqtt-diag/tests' output.mkdir(parents=True, exist_ok=True) (output / 'MQTTClient.h').write_text(r''' #ifndef TEST_MQTT_CLIENT_H #define TEST_MQTT_CLIENT_H typedef struct Network Network; struct Network { int (*mqttread)(Network *, unsigned char *, int, int); int (*mqttwrite)(Network *, unsigned char *, int, int); }; typedef struct { Network *ipstack; unsigned int command_timeout_ms; int isconnected; } MQTTClient; typedef struct { unsigned char MQTTVersion, cleansession; unsigned short keepAliveInterval; } MQTTPacket_connectData; typedef struct { unsigned char rc, sessionPresent; } MQTTConnackData; int MQTTConnectWithResults(MQTTClient *, MQTTPacket_connectData *, MQTTConnackData *); unsigned int ql_rtos_get_systicks(void); #endif ''') (output / 'sockets.h').write_text('int ql_get_soc_errno(void);\n') harness = r''' #include #include #include #include "mqtt_connect_diag.h" static unsigned int ticks; static int mode, offset, writes, reads; unsigned int ql_rtos_get_systicks(void) { return ticks; } int ql_get_soc_errno(void) { return 104; } static int fake_write(Network *n, unsigned char *buf, int size, int timeout) { (void)n; assert(timeout == 30000 && size == 19); assert(memcmp(buf, "PRIVATE_TEST_SECRET", 19) == 0); ++writes; ticks += 2; return mode == 2 ? -1 : size; } static int fake_read(Network *n, unsigned char *buf, int size, int timeout) { unsigned char response[] = {0x20, 2, 0, 0}; (void)n; assert(timeout == 30000 && (size == 1 || size == 2)); ++reads; ticks += 3; if (mode == 3) return -1; if (mode == 4) return 0; if (mode == 1) response[3] = 5; if (mode == 5) response[0] = 0x30; if (mode == 7) { response[2] = 1; response[3] = 5; } memcpy(buf, response + offset, size); offset += size; return size; } int MQTTConnectWithResults(MQTTClient *client, MQTTPacket_connectData *options, MQTTConnackData *ack) { unsigned char packet[] = "PRIVATE_TEST_SECRET"; unsigned char response[4] = {0}; int result; assert(options->MQTTVersion == 3); assert(ack->rc == 255); if (mode == 6) return -1; result = client->ipstack->mqttwrite(client->ipstack, packet, 19, 30000); if (result != 19) { assert(result == -1); return -1; } /* SDK reads fixed header, remaining length, then the two-byte body. */ result = client->ipstack->mqttread(client->ipstack, response, 1, 30000); if (mode == 3 || mode == 4) { assert(result == (mode == 3 ? -1 : 0)); return -1; } assert(result == 1); assert(client->ipstack->mqttread(client->ipstack, response + 1, 1, 30000) == 1); assert(client->ipstack->mqttread(client->ipstack, response + 2, 2, 30000) == 2); assert(response[1] == 2); return mode == 0 ? 0 : (mode == 1 ? 5 : -1); } int main(void) { Network network = {fake_read, fake_write}; MQTTClient client = {&network, 30000, 0}; MQTTPacket_connectData options = {3, 0, 60}; for (mode = 0; mode < 8; ++mode) { int expected = mode == 0 ? 0 : (mode == 1 ? 5 : -1); ticks = mode == 0 ? 0xfffffffeU : 0; offset = writes = reads = 0; printf("CASE %d\n", mode); assert(talkingq_mqtt_connect_diagnosed(&client, &options) == expected); assert(network.mqttread == fake_read && network.mqttwrite == fake_write); assert(writes == (mode == 6 ? 0 : 1)); if (mode == 6 || mode == 2) assert(reads == 0); } return 0; } ''' (output / 'test.c').write_text(harness) include = root / 'ql-application/threadx/interface/custom_app/inc' source = root / 'ql-application/threadx/interface/custom_app/mqtt_connect_diag.c' subprocess.run(['cl', '/nologo', '/W4', '/WX', '/TC', '/I' + str(output), '/I' + str(include), str(source), str(output / 'test.c'), '/Fe' + str(output / 'test.exe')], cwd=output, check=True) result = subprocess.check_output([str(output / 'test.exe')], text=True) assert 'PRIVATE_TEST_SECRET' not in result cases = [part for part in result.split('CASE ')[1:]] assert len(cases) == 8 assert 'CONNACK code=0 reason=accepted' in cases[0] and 'elapsed_ms=55' in cases[0] assert 'CONNACK code=5 reason=not_authorized' in cases[1] assert 'write request=19 rc=-1' in cases[2] assert 'read request=1 rc=-1' in cases[3] assert 'read request=1 rc=0' in cases[4] assert 'no valid initial CONNACK' in cases[5] assert 'failed before transport write' in cases[6] assert 'no valid initial CONNACK' in cases[7] for case in cases[2:]: assert '[MQTT-DIAG] CONNACK code=' not in case (output / 'test-output.log').write_text(result) print('PASS: transport arguments/return values, callback restoration, split CONNACK, rejection, invalid response, errors, no-I/O failure, tick wrap and credential redaction')