1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 #include <stdio.h>
12 #include <setjmp.h>
13 #include <cmocka.h>  /* macros: https://api.cmocka.org/group__cmocka__asserts.html */
14 
15 #include "nx_api.h"
16 #include "nx_azure_iot_hub_client.h"
17 #include "nx_azure_iot_cert.h"
18 #include "nx_azure_iot_ciphersuites.h"
19 
20 
21 #define DEMO_DHCP_DISABLE
22 #define DEMO_IPV4_ADDRESS         IP_ADDRESS(192, 168, 100, 33)
23 #define DEMO_IPV4_MASK            0xFFFFFF00UL
24 #define DEMO_GATEWAY_ADDRESS      IP_ADDRESS(192, 168, 100, 1)
25 #define DEMO_DNS_SERVER_ADDRESS   IP_ADDRESS(192, 168, 100, 1)
26 #define NETWORK_DRIVER            _nx_ram_network_driver
27 
28 /* Include main.c in the test case since we need to disable DHCP in this test. */
29 #include "main.c"
30 
31 #ifndef DEMO_CLOUD_STACK_SIZE
32 #define DEMO_CLOUD_STACK_SIZE           2048
33 #endif /* DEMO_CLOUD_STACK_SIZE */
34 
35 #ifndef DEMO_CLOUD_THREAD_PRIORITY
36 #define DEMO_CLOUD_THREAD_PRIORITY      (4)
37 #endif /* DEMO_CLOUD_THREAD_PRIORITY */
38 
39 #ifndef MAXIMUM_PAYLOAD_LENGTH
40 #define MAXIMUM_PAYLOAD_LENGTH          10240
41 #endif /* MAXIMUM_PAYLOAD_LENGTH */
42 
43 #define MQTT_CLIENT_GET(c)              ((c) -> nx_azure_iot_hub_client_resource.resource_mqtt)
44 #define TX_MUTEX_GET(c)                 ((c) -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr)
45 
46 typedef VOID (*NX_AZURE_TEST_FN)();
47 
48 
49 static UCHAR g_hostname[] = "unit-test.iot-azure.com";
50 static UCHAR g_device_id[] = "unit_test_device";
51 
52 static const UINT test_dt_document_response_status = 201;
53 static const UINT test_dt_reported_properties_response_status = 204;
54 static const UINT test_request_id = 1;
55 
56 static const CHAR test_device_twin_reported_properties_response_topic[] = "$iothub/twin/res/204/?$rid=1&$version=6";
57 static const CHAR test_device_twin_reported_properties_throttled_response_topic[] = "$iothub/twin/res/429/?$rid=1";
58 static const CHAR test_device_twin_reported_properties_response_payload[] = "";
59 static const UINT test_reported_properties_response_id = 1;
60 static const CHAR test_device_twin_document_response_topic[] = "$iothub/twin/res/201/?$rid=2";
61 static const CHAR test_device_twin_document_response_payload[] = "{ \
62     \"desired\": { \
63         \"telemetrySendFrequency\": \"5m\", \
64         \"$version\": 12 \
65     }, \
66     \"reported\": { \
67         \"telemetrySendFrequency\": \"5m\", \
68         \"batteryLevel\": 55, \
69         \"$version\": 123 \
70     } \
71 }";
72 static const CHAR test_device_twin_document_response_throttled_topic[] = "$iothub/twin/res/429/?$rid=2";
73 static const UINT test_device_twin_document_response_id = 2;
74 static const CHAR test_device_twin_desired_properties_response_topic[] = "$iothub/twin/PATCH/properties/desired/?$version=10";
75 static const CHAR test_device_twin_desired_properties_response_payload[] = "{ \
76     \"telemetrySendFrequency\": \"5m\", \
77     \"route\": null, \
78     \"$version\": 8 \
79 }";
80 static CHAR fixed_reported_properties[] = "{\"sample_report\": \"OK\"}";
81 
82 static UINT g_total_append = 0;
83 static UINT g_failed_append_index = 0;
84 static UINT g_total_allocation = 0;
85 static UINT g_failed_allocation_index = -1;
86 static NX_IP* g_ip_ptr;
87 static NX_PACKET_POOL* g_pool_ptr;
88 static NX_DNS* g_dns_ptr;
89 static ULONG g_available_packet;
90 static CHAR *g_expected_message;
91 static UINT g_response_status;
92 static UINT g_request_id;
93 
94 extern UINT _nxd_mqtt_client_append_message(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, CHAR *message,
95                                             UINT length, ULONG wait_option);
96 extern UINT _nxd_mqtt_client_set_fixed_header(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr,
97                                               UCHAR control_header, UINT length, UINT wait_option);
98 
99 static NX_AZURE_IOT iot;
100 static NX_AZURE_IOT_HUB_CLIENT iot_client;
101 static NX_SECURE_X509_CERT root_ca_cert;
102 static UCHAR metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE];
103 static ULONG demo_cloud_thread_stack[DEMO_CLOUD_STACK_SIZE / sizeof(ULONG)];
104 static UCHAR message_payload[MAXIMUM_PAYLOAD_LENGTH];
105 static UCHAR result_buffer[MAXIMUM_PAYLOAD_LENGTH];
106 static VOID (*test_receive_notify)(NXD_MQTT_CLIENT *client_ptr, UINT message_count) = NX_NULL;
107 
__wrap_nx_azure_iot_security_module_enable(NX_AZURE_IOT * nx_azure_iot_ptr)108 UINT __wrap_nx_azure_iot_security_module_enable(NX_AZURE_IOT *nx_azure_iot_ptr)
109 {
110     printf("HIJACKED: %s\n", __func__);
111     return(NX_AZURE_IOT_SUCCESS);
112 }
113 
__wrap_nx_azure_iot_security_module_disable(NX_AZURE_IOT * nx_azure_iot_ptr)114 UINT __wrap_nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr)
115 {
116     printf("HIJACKED: %s\n", __func__);
117     return(NX_AZURE_IOT_SUCCESS);
118 }
119 
__wrap__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT * client_ptr,VOID (* receive_notify)(NXD_MQTT_CLIENT * client_ptr,UINT message_count))120 UINT __wrap__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT *client_ptr,
121                                                  VOID (*receive_notify)(NXD_MQTT_CLIENT *client_ptr, UINT message_count))
122 {
123     printf("HIJACKED: %s\n", __func__);
124     test_receive_notify = receive_notify;
125     return(NX_AZURE_IOT_SUCCESS);
126 }
127 
__wrap__nxde_mqtt_client_subscribe(NXD_MQTT_CLIENT * client_ptr,CHAR * topic_name,UINT topic_name_length,UINT QoS)128 UINT __wrap__nxde_mqtt_client_subscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name,
129                                         UINT topic_name_length, UINT QoS)
130 {
131     printf("HIJACKED: %s\n", __func__);
132 
133     iot_client.nx_azure_iot_hub_client_properties_subscribe_ack = NX_TRUE;
134 
135     return((UINT)mock());
136 }
137 
__wrap__nxde_mqtt_client_unsubscribe(NXD_MQTT_CLIENT * client_ptr,CHAR * topic_name,UINT topic_name_length,UINT QoS)138 UINT __wrap__nxde_mqtt_client_unsubscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name,
139                                           UINT topic_name_length, UINT QoS)
140 {
141     printf("HIJACKED: %s\n", __func__);
142     return((UINT)mock());
143 }
144 
145 UINT __real__nx_packet_data_append(NX_PACKET *packet_ptr, VOID *data_start, ULONG data_size,
146                                      NX_PACKET_POOL *pool_ptr, ULONG wait_option);
__wrap__nx_packet_data_append(NX_PACKET * packet_ptr,VOID * data_start,ULONG data_size,NX_PACKET_POOL * pool_ptr,ULONG wait_option)147 UINT __wrap__nx_packet_data_append(NX_PACKET *packet_ptr, VOID *data_start, ULONG data_size,
148                                      NX_PACKET_POOL *pool_ptr, ULONG wait_option)
149 {
150     printf("HIJACKED: %s\n", __func__);
151 
152     if (g_failed_append_index == g_total_append)
153     {
154         return(NX_NOT_SUCCESSFUL);
155     }
156 
157     g_total_append++;
158     return __real__nx_packet_data_append(packet_ptr, data_start, data_size, pool_ptr, wait_option);
159 }
160 
161 UINT __real_nx_azure_iot_buffer_allocate(NX_AZURE_IOT *nx_azure_iot_ptr, UCHAR **buffer_pptr,
162                                          UINT *buffer_size, VOID **buffer_context);
__wrap_nx_azure_iot_buffer_allocate(NX_AZURE_IOT * nx_azure_iot_ptr,UCHAR ** buffer_pptr,UINT * buffer_size,VOID ** buffer_context)163 UINT __wrap_nx_azure_iot_buffer_allocate(NX_AZURE_IOT *nx_azure_iot_ptr, UCHAR **buffer_pptr,
164                                          UINT *buffer_size, VOID **buffer_context)
165 {
166     printf("HIJACKED: %s\n", __func__);
167 
168     if (g_failed_allocation_index == g_total_allocation)
169     {
170         return(NX_NOT_SUCCESSFUL);
171     }
172 
173     g_total_allocation++;
174     return __real_nx_azure_iot_buffer_allocate(nx_azure_iot_ptr, buffer_pptr, buffer_size, buffer_context);
175 }
176 
__wrap__nxd_mqtt_client_publish_packet_send(NXD_MQTT_CLIENT * client_ptr,NX_PACKET * packet_ptr,USHORT packet_id,UINT QoS,ULONG wait_option)177 UINT __wrap__nxd_mqtt_client_publish_packet_send(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr,
178                                                  USHORT packet_id, UINT QoS, ULONG wait_option)
179 {
180 UINT status = (UINT)mock();
181 
182     printf("HIJACKED: %s\n", __func__);
183     tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr);
184 
185     if (status)
186     {
187         return(status);
188     }
189 
190     assert_int_equal(QoS, 0);
191 
192     /* packet ownership taken and released */
193     nx_packet_release(packet_ptr);
194 
195     return(status);
196 }
197 
__wrap__nxde_mqtt_client_secure_connect(NXD_MQTT_CLIENT * client_ptr,NXD_ADDRESS * server_ip,UINT server_port,UINT (* tls_setup)(NXD_MQTT_CLIENT * client_ptr,NX_SECURE_TLS_SESSION *,NX_SECURE_X509_CERT *,NX_SECURE_X509_CERT *),UINT keepalive,UINT clean_session,ULONG wait_option)198 UINT __wrap__nxde_mqtt_client_secure_connect(NXD_MQTT_CLIENT *client_ptr, NXD_ADDRESS *server_ip, UINT server_port,
199                                              UINT (*tls_setup)(NXD_MQTT_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *,
200                                                                NX_SECURE_X509_CERT *, NX_SECURE_X509_CERT *),
201                                              UINT keepalive, UINT clean_session, ULONG wait_option)
202 {
203     printf("HIJACKED: %s\n", __func__);
204 
205     tx_thread_suspend(&(iot.nx_azure_iot_ip_ptr -> nx_ip_thread));
206     client_ptr -> nxd_mqtt_client_state = NXD_MQTT_CLIENT_STATE_CONNECTED;
207     client_ptr -> nxd_mqtt_client_packet_identifier = 1;
208     client_ptr -> nxd_mqtt_tls_session.nx_secure_tls_id = NX_SECURE_TLS_ID;
209     client_ptr -> nxd_mqtt_tls_session.nx_secure_tls_local_session_active = NX_FALSE;
210     client_ptr -> nxd_mqtt_tls_session.nx_secure_tls_tcp_socket = &client_ptr -> nxd_mqtt_client_socket;
211     client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_connect_ip.nxd_ip_version = NX_IP_VERSION_V4;
212     client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_state = NX_TCP_ESTABLISHED;
213 
214     return(NXD_MQTT_SUCCESS);
215 }
216 
__wrap__nxde_mqtt_client_disconnect(NXD_MQTT_CLIENT * client_ptr)217 UINT __wrap__nxde_mqtt_client_disconnect(NXD_MQTT_CLIENT *client_ptr)
218 {
219     printf("HIJACKED: %s\n", __func__);
220     client_ptr -> nxd_mqtt_client_state = NXD_MQTT_CLIENT_STATE_IDLE;
221     client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_state = NX_TCP_CLOSED;
222     return(NXD_MQTT_SUCCESS);
223 }
224 
__wrap__nxde_dns_host_by_name_get(NX_DNS * dns_ptr,UCHAR * host_name,NXD_ADDRESS * host_address_ptr,ULONG wait_option,UINT lookup_type)225 UINT __wrap__nxde_dns_host_by_name_get(NX_DNS *dns_ptr, UCHAR *host_name, NXD_ADDRESS *host_address_ptr,
226                                        ULONG wait_option, UINT lookup_type)
227 {
228     printf("HIJACKED: %s\n", __func__);
229     host_address_ptr -> nxd_ip_address.v4 = IP_ADDRESS(127, 0, 0, 1);
230     return(NX_DNS_SUCCESS);
231 }
232 
on_receive_callback(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,VOID * arg)233 static VOID on_receive_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *arg)
234 {
235     *((UINT *)arg) = 1;
236 }
237 
mqtt_client_set_fixed_header(NXD_MQTT_CLIENT * client_ptr,NX_PACKET * packet_ptr,UCHAR control_header,UINT length,UINT wait_option)238 static UINT mqtt_client_set_fixed_header(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, UCHAR control_header, UINT length, UINT wait_option)
239 {
240 UCHAR  fixed_header[5];
241 UCHAR *byte = fixed_header;
242 UINT   count = 0;
243 UINT   ret;
244 
245     *byte = control_header;
246     byte++;
247 
248     do
249     {
250         if (length & 0xFFFFFF80)
251         {
252             *(byte + count) = (UCHAR)((length & 0x7F) | 0x80);
253         }
254         else
255         {
256             *(byte + count) = length & 0x7F;
257         }
258         length = length >> 7;
259 
260         count++;
261     } while (length != 0);
262 
263     ret = __real__nx_packet_data_append(packet_ptr, fixed_header, count + 1,
264                                         client_ptr -> nxd_mqtt_client_packet_pool_ptr, wait_option);
265 
266     return(ret);
267 }
268 
construct_device_twin_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR * topic,ULONG topic_len,const UCHAR * message_payload_ptr,ULONG message_payload_length,NX_PACKET ** packet_pptr)269 static VOID construct_device_twin_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
270                                            const UCHAR *topic, ULONG topic_len,
271                                            const UCHAR *message_payload_ptr, ULONG message_payload_length,
272                                            NX_PACKET **packet_pptr)
273 {
274 NX_PACKET *packet_ptr;
275 ULONG total_length;
276 ULONG topic_length = topic_len;
277 UCHAR bytes[2];
278 UINT i;
279 
280     assert_int_equal(nx_packet_allocate(iot.nx_azure_iot_pool_ptr, &packet_ptr, 0, NX_NO_WAIT),
281                      NX_AZURE_IOT_SUCCESS);
282     total_length = topic_length + 2 + 2 + message_payload_length; /* Two bytes for fixed topic_length field
283                                                                      and two bytes for packet id. */
284 
285     /* Set fixed header. */
286     assert_int_equal(mqtt_client_set_fixed_header(&(MQTT_CLIENT_GET(hub_client_ptr)), packet_ptr,
287                                                   (UCHAR)((MQTT_CONTROL_PACKET_TYPE_PUBLISH << 4) | MQTT_PUBLISH_QOS_LEVEL_1),
288                                                   total_length, NX_NO_WAIT),
289                      NX_AZURE_IOT_SUCCESS);
290 
291     /* Set topic length. */
292     bytes[0] = (topic_length >> 8) & 0xFF;
293     bytes[1] = topic_length & 0xFF;
294     assert_int_equal(__real__nx_packet_data_append(packet_ptr, bytes, sizeof(bytes),
295                                                    iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
296                      NX_AZURE_IOT_SUCCESS);
297 
298     /* Set topic. */
299     assert_int_equal(__real__nx_packet_data_append(packet_ptr, (VOID *)topic, topic_len,
300                                                    iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
301                      NX_AZURE_IOT_SUCCESS);
302     /* Set packet ID. The value does not matter. */
303     assert_int_equal(__real__nx_packet_data_append(packet_ptr, bytes, sizeof(bytes),
304                                                    iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
305                      NX_AZURE_IOT_SUCCESS);
306 
307     /* Set message payload. */
308     if (message_payload_length > 0)
309     {
310         assert_int_equal(__real__nx_packet_data_append(packet_ptr, (VOID *)message_payload_ptr, message_payload_length,
311                                                        iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
312                          NX_AZURE_IOT_SUCCESS);
313     }
314 
315     *packet_pptr = packet_ptr;
316 }
317 
generate_device_twin_reported_properties_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)318 static VOID generate_device_twin_reported_properties_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
319 {
320 NX_PACKET *packet_ptr;
321 
322     construct_device_twin_response(hub_client_ptr, test_device_twin_reported_properties_response_topic,
323                                    sizeof(test_device_twin_reported_properties_response_topic) - 1,
324                                    test_device_twin_reported_properties_response_payload,
325                                    sizeof(test_device_twin_reported_properties_response_payload) - 1,
326                                    &packet_ptr);
327 
328     /* Simulate callback from MQTT layer.  */
329     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_head = packet_ptr;
330     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_depth = 1;
331     tx_mutex_get(TX_MUTEX_GET(hub_client_ptr), NX_WAIT_FOREVER);
332     test_receive_notify(&(MQTT_CLIENT_GET(hub_client_ptr)), 1);
333     tx_mutex_put(TX_MUTEX_GET(hub_client_ptr));
334 }
335 
generate_device_twin_reported_properties_throttled_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)336 static VOID generate_device_twin_reported_properties_throttled_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
337 {
338 NX_PACKET *packet_ptr;
339 
340     construct_device_twin_response(hub_client_ptr, test_device_twin_reported_properties_throttled_response_topic,
341                                    sizeof(test_device_twin_reported_properties_throttled_response_topic) - 1,
342                                    NX_NULL, 0, &packet_ptr);
343 
344     /* Simulate callback from MQTT layer.  */
345     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_head = packet_ptr;
346     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_depth = 1;
347     tx_mutex_get(TX_MUTEX_GET(hub_client_ptr), NX_WAIT_FOREVER);
348     test_receive_notify(&(MQTT_CLIENT_GET(hub_client_ptr)), 1);
349     tx_mutex_put(TX_MUTEX_GET(hub_client_ptr));
350 }
351 
generate_device_twin_document_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)352 static VOID generate_device_twin_document_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
353 {
354 NX_PACKET *packet_ptr;
355 
356     construct_device_twin_response(hub_client_ptr, test_device_twin_document_response_topic,
357                                    sizeof(test_device_twin_document_response_topic) - 1,
358                                    test_device_twin_document_response_payload,
359                                    sizeof(test_device_twin_document_response_payload) - 1,
360                                    &packet_ptr);
361 
362     /* Simulate callback from MQTT layer.  */
363     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_head = packet_ptr;
364     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_depth = 1;
365     tx_mutex_get(TX_MUTEX_GET(hub_client_ptr), NX_WAIT_FOREVER);
366     test_receive_notify(&(MQTT_CLIENT_GET(hub_client_ptr)), 1);
367     tx_mutex_put(TX_MUTEX_GET(hub_client_ptr));
368 }
369 
generate_device_twin_document_throttled_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)370 static VOID generate_device_twin_document_throttled_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
371 {
372 NX_PACKET *packet_ptr;
373 
374     construct_device_twin_response(hub_client_ptr, test_device_twin_document_response_throttled_topic,
375                                    sizeof(test_device_twin_document_response_throttled_topic) - 1,
376                                    "{}", sizeof("{}") - 1, &packet_ptr);
377 
378     /* Simulate callback from MQTT layer.  */
379     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_head = packet_ptr;
380     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_depth = 1;
381     tx_mutex_get(TX_MUTEX_GET(hub_client_ptr), NX_WAIT_FOREVER);
382     test_receive_notify(&MQTT_CLIENT_GET(hub_client_ptr), 1);
383     tx_mutex_put(TX_MUTEX_GET(hub_client_ptr));
384 }
385 
generate_device_twin_desired_properties_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)386 static VOID generate_device_twin_desired_properties_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
387 {
388 NX_PACKET *packet_ptr;
389 
390     construct_device_twin_response(hub_client_ptr, test_device_twin_desired_properties_response_topic,
391                                    sizeof(test_device_twin_desired_properties_response_topic) - 1,
392                                    test_device_twin_desired_properties_response_payload,
393                                    sizeof(test_device_twin_desired_properties_response_payload) - 1,
394                                    &packet_ptr);
395 
396     /* Simulate callback from MQTT layer.  */
397     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_head = packet_ptr;
398     MQTT_CLIENT_GET(hub_client_ptr).message_receive_queue_depth = 1;
399     tx_mutex_get(TX_MUTEX_GET(hub_client_ptr), NX_WAIT_FOREVER);
400     test_receive_notify(&(MQTT_CLIENT_GET(hub_client_ptr)), 1);
401     tx_mutex_put(TX_MUTEX_GET(hub_client_ptr));
402 }
403 
test_response_callback(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT request_id,UINT response_status,ULONG version,VOID * args)404 static VOID test_response_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT request_id,
405                                    UINT response_status, ULONG version, VOID *args)
406 {
407     g_response_status = response_status;
408     g_request_id = request_id;
409 }
410 
reset_global_state()411 static VOID reset_global_state()
412 {
413     /* reset global state */
414     g_failed_append_index = (UINT)-1;
415     g_total_append = 0;
416     g_failed_allocation_index = (UINT)-1;
417     g_total_allocation = 0;
418     g_expected_message = NX_NULL;
419     g_response_status = 0;
420     g_request_id = 0;
421 }
422 
423 /* Hook execute before all tests. */
test_suit_begin()424 static VOID test_suit_begin()
425 {
426 
427     /* Initialize root certificate.  */
428     assert_int_equal(nx_secure_x509_certificate_initialize(&root_ca_cert,
429                                                            (UCHAR *)_nx_azure_iot_root_cert,
430                                                            (USHORT)_nx_azure_iot_root_cert_size,
431                                                            NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE),
432                      NX_AZURE_IOT_SUCCESS);
433 
434     /* Initialize azure iot handle.  */
435     assert_int_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT",
436                                          g_ip_ptr, g_pool_ptr, g_dns_ptr,
437                                          (UCHAR *)demo_cloud_thread_stack,
438                                          sizeof(demo_cloud_thread_stack),
439                                          DEMO_CLOUD_THREAD_PRIORITY, unix_time_get),
440                      NX_AZURE_IOT_SUCCESS);
441 
442     /* Initialize azure iot handle.  */
443     assert_int_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
444                                                         g_hostname, sizeof(g_hostname),
445                                                         g_device_id, sizeof(g_device_id),
446                                                         "", 0,
447                                                         _nx_azure_iot_tls_supported_crypto,
448                                                         _nx_azure_iot_tls_supported_crypto_size,
449                                                         _nx_azure_iot_tls_ciphersuite_map,
450                                                         _nx_azure_iot_tls_ciphersuite_map_size,
451                                                         metadata_buffer, sizeof(metadata_buffer),
452                                                         &root_ca_cert),
453                      NX_AZURE_IOT_SUCCESS);
454 
455     /* Record number of available packet before test */
456     g_available_packet = g_pool_ptr -> nx_packet_pool_available;
457 
458     /* Connect IoTHub client */
459     assert_int_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, NX_WAIT_FOREVER),
460                      NX_AZURE_IOT_SUCCESS);
461 }
462 
463 /* Hook execute after all tests are executed successfully */
test_suit_end()464 static VOID test_suit_end()
465 {
466 
467     /* Disconnect IoTHub client */
468     assert_int_equal(nx_azure_iot_hub_client_disconnect(&iot_client), NX_AZURE_IOT_SUCCESS);
469 
470     /* Check if all the packet are released */
471     assert_int_equal(g_pool_ptr -> nx_packet_pool_available, g_available_packet);
472 
473     /* Deinitialize IoTHub Client */
474     assert_int_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
475                      NX_AZURE_IOT_SUCCESS);
476 
477     /* SUCCESS: iot is deleted. */
478     assert_int_equal(nx_azure_iot_delete(&iot), NX_AZURE_IOT_SUCCESS);
479 }
480 
481 /* Hook executed before every test */
test_begin()482 static VOID test_begin()
483 {
484     reset_global_state();
485 
486     /* Reset the number of request sent */
487     iot_client.nx_azure_iot_hub_client_request_id = 0;
488 }
489 
490 /* Hook execute after all tests are executed successfully */
test_end()491 static VOID test_end()
492 {
493 }
494 
495 /**
496  * Test device twin enable with invalid argument failed.
497  *
498  **/
test_nx_azure_iot_hub_client_device_twin_enable_invalid_argument_failure()499 static VOID test_nx_azure_iot_hub_client_device_twin_enable_invalid_argument_failure()
500 {
501     printf("test starts =>: %s\n", __func__);
502 
503     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_enable(NX_NULL),
504                          NX_AZURE_IOT_SUCCESS);
505 }
506 
507 /**
508  * Test device twin enable with unsuccessful subscribe failed.
509  *
510  **/
test_nx_azure_iot_hub_client_device_twin_enable_failure()511 static VOID test_nx_azure_iot_hub_client_device_twin_enable_failure()
512 {
513     printf("test starts =>: %s\n", __func__);
514 
515     will_return(__wrap__nxde_mqtt_client_subscribe, NX_NOT_SUCCESSFUL);
516     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
517                          NX_AZURE_IOT_SUCCESS);
518 
519     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
520     will_return(__wrap__nxde_mqtt_client_subscribe, NX_NOT_SUCCESSFUL);
521     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
522                          NX_AZURE_IOT_SUCCESS);
523 }
524 
525 /**
526  * Test device twin enable succeeds.
527  *
528  **/
test_nx_azure_iot_hub_client_device_twin_enable_success()529 static VOID test_nx_azure_iot_hub_client_device_twin_enable_success()
530 {
531     printf("test starts =>: %s\n", __func__);
532 
533     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
534     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
535     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
536                      NX_AZURE_IOT_SUCCESS);
537 }
538 
539 /**
540  * Test device twin disable with invalid argument failed.
541  *
542  **/
test_nx_azure_iot_hub_client_device_twin_disable_invalid_argument_failure()543 static VOID test_nx_azure_iot_hub_client_device_twin_disable_invalid_argument_failure()
544 {
545     printf("test starts =>: %s\n", __func__);
546 
547     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_disable(NX_NULL),
548                          NX_AZURE_IOT_SUCCESS);
549 }
550 
551 /**
552  * Test device twin disable with unsuccessful un-subscribe failed.
553  *
554  **/
test_nx_azure_iot_hub_client_device_twin_disable_failure()555 static VOID test_nx_azure_iot_hub_client_device_twin_disable_failure()
556 {
557     printf("test starts =>: %s\n", __func__);
558 
559     will_return(__wrap__nxde_mqtt_client_unsubscribe, NX_NOT_SUCCESSFUL);
560     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_disable(&iot_client),
561                          NX_AZURE_IOT_SUCCESS);
562 
563     will_return(__wrap__nxde_mqtt_client_unsubscribe, NX_AZURE_IOT_SUCCESS);
564     will_return(__wrap__nxde_mqtt_client_unsubscribe, NX_NOT_SUCCESSFUL);
565     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_disable(&iot_client),
566                          NX_AZURE_IOT_SUCCESS);
567 }
568 
569 /**
570  * Test device twin disable succeeds.
571  *
572  **/
test_nx_azure_iot_hub_client_device_twin_disable_success()573 static VOID test_nx_azure_iot_hub_client_device_twin_disable_success()
574 {
575     printf("test starts =>: %s\n", __func__);
576 
577     will_return_always(__wrap__nxde_mqtt_client_unsubscribe, NX_AZURE_IOT_SUCCESS);
578     assert_int_equal(nx_azure_iot_hub_client_device_twin_disable(&iot_client),
579                      NX_AZURE_IOT_SUCCESS);
580 }
581 
582 /**
583  * Test device twin reported property callback set with invalid argument failed.
584  *
585  **/
test_nx_azure_iot_hub_client_reported_properties_response_callback_set_invalid_argument_failure()586 static VOID test_nx_azure_iot_hub_client_reported_properties_response_callback_set_invalid_argument_failure()
587 {
588     printf("test starts =>: %s\n", __func__);
589 
590     assert_int_not_equal(nx_azure_iot_hub_client_reported_properties_response_callback_set(NX_NULL,
591                                                                                            NX_NULL, NX_NULL),
592                          NX_AZURE_IOT_SUCCESS);
593 }
594 
595 /**
596  * Test device twin reported properties callback set succeed.
597  *
598  **/
test_nx_azure_iot_hub_client_reported_properties_response_callback_set_success()599 static VOID test_nx_azure_iot_hub_client_reported_properties_response_callback_set_success()
600 {
601     printf("test starts =>: %s\n", __func__);
602 
603     assert_int_equal(nx_azure_iot_hub_client_reported_properties_response_callback_set(&iot_client,
604                                                                                        test_response_callback, NX_NULL),
605                      NX_AZURE_IOT_SUCCESS);
606 }
607 
608 /**
609  * Test old API reported properties callback set with invalid argument failed.
610  *
611  **/
test_nx_azure_iot_hub_client_report_properties_response_callback_set_invalid_argument_failure()612 static VOID test_nx_azure_iot_hub_client_report_properties_response_callback_set_invalid_argument_failure()
613 {
614     printf("test starts =>: %s\n", __func__);
615 
616     assert_int_not_equal(nx_azure_iot_hub_client_report_properties_response_callback_set(NX_NULL,
617                                                                                          NX_NULL, NX_NULL),
618                          NX_AZURE_IOT_SUCCESS);
619 }
620 
621 /**
622  * Test old API reported properties callback set succeed.
623  *
624  **/
test_nx_azure_iot_hub_client_report_properties_response_callback_set_success()625 static VOID test_nx_azure_iot_hub_client_report_properties_response_callback_set_success()
626 {
627     printf("test starts =>: %s\n", __func__);
628 
629     assert_int_equal(nx_azure_iot_hub_client_report_properties_response_callback_set(&iot_client,
630                                                                                      test_response_callback, NX_NULL),
631                      NX_AZURE_IOT_SUCCESS);
632 }
633 
634 /**
635  * Test device twin send reported properties fail if invalid argument is passed.
636  *
637  **/
test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_invalid_argument_failure()638 static VOID test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_invalid_argument_failure()
639 {
640     printf("test starts =>: %s\n", __func__);
641 
642     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_reported_properties_send(NX_NULL,
643                                                                                       fixed_reported_properties,
644                                                                                       sizeof(fixed_reported_properties) - 1,
645                                                                                       &g_request_id, &g_response_status,
646                                                                                       NX_NULL, 0),
647                          NX_AZURE_IOT_SUCCESS);
648 }
649 
650 /**
651  * Test device twin send reported properties fail if publish failed.
652  *
653  **/
test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_publish_failure()654 static VOID test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_publish_failure()
655 {
656     printf("test starts =>: %s\n", __func__);
657 
658     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
659     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
660     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
661                      NX_AZURE_IOT_SUCCESS);
662     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_NOT_SUCCESSFUL);
663 
664     assert_int_equal(nx_azure_iot_hub_client_reported_properties_response_callback_set(&iot_client,
665                                                                                        test_response_callback, NX_NULL),
666                      NX_AZURE_IOT_SUCCESS);
667     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_reported_properties_send(&iot_client,
668                                                                                       fixed_reported_properties,
669                                                                                       sizeof(fixed_reported_properties) - 1,
670                                                                                       &g_request_id, &g_response_status,
671                                                                                       NX_NULL, 0),
672                          NX_AZURE_IOT_SUCCESS);
673 }
674 
675 /**
676  * Test device twin send reported properties succeed.
677  *
678  **/
test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_success()679 static VOID test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_success()
680 {
681 UINT request_id = 0xFFFFFFFF;
682 
683     printf("test starts =>: %s\n", __func__);
684 
685     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
686     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
687     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
688                      NX_AZURE_IOT_SUCCESS);
689     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_AZURE_IOT_SUCCESS);
690 
691     assert_int_equal(nx_azure_iot_hub_client_reported_properties_response_callback_set(&iot_client,
692                                                                                        test_response_callback, NX_NULL),
693                      NX_AZURE_IOT_SUCCESS);
694     assert_int_equal(nx_azure_iot_hub_client_device_twin_reported_properties_send(&iot_client,
695                                                                                   fixed_reported_properties,
696                                                                                   sizeof(fixed_reported_properties) - 1,
697                                                                                   &request_id, &g_response_status,
698                                                                                   NX_NULL, 0),
699                      NX_AZURE_IOT_NO_PACKET);
700 
701     generate_device_twin_reported_properties_response(&iot_client);
702 
703     assert_int_not_equal(0xFFFFFFFF, request_id);
704     assert_int_equal(g_request_id, request_id);
705     assert_int_equal(g_response_status, test_dt_reported_properties_response_status);
706 }
707 
708 /**
709  * Test device twin send reported properties throttled.
710  *
711  **/
test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_throttled()712 static VOID test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_throttled()
713 {
714 UINT request_id = 0xFFFFFFFF;
715 
716     printf("test starts =>: %s\n", __func__);
717 
718     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
719     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
720     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
721                      NX_AZURE_IOT_SUCCESS);
722     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_AZURE_IOT_SUCCESS);
723 
724     assert_int_equal(nx_azure_iot_hub_client_reported_properties_response_callback_set(&iot_client,
725                                                                                        test_response_callback, NX_NULL),
726                      NX_AZURE_IOT_SUCCESS);
727     assert_int_equal(nx_azure_iot_hub_client_device_twin_reported_properties_send(&iot_client,
728                                                                                   fixed_reported_properties,
729                                                                                   sizeof(fixed_reported_properties) - 1,
730                                                                                   &request_id, &g_response_status,
731                                                                                   NX_NULL, 0),
732                      NX_AZURE_IOT_NO_PACKET);
733 
734     generate_device_twin_reported_properties_throttled_response(&iot_client);
735 
736     assert_int_equal(nx_azure_iot_hub_client_device_twin_reported_properties_send(&iot_client,
737                                                                                   fixed_reported_properties,
738                                                                                   sizeof(fixed_reported_properties) - 1,
739                                                                                   &request_id, &g_response_status,
740                                                                                   NX_NULL, 0),
741                      NX_AZURE_IOT_THROTTLED);
742 
743     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_AZURE_IOT_SUCCESS);
744     while (nx_azure_iot_hub_client_device_twin_reported_properties_send(&iot_client,
745                                                                         fixed_reported_properties,
746                                                                         sizeof(fixed_reported_properties) - 1,
747                                                                         &request_id, &g_response_status,
748                                                                         NX_NULL, 0) != NX_AZURE_IOT_NO_PACKET)
749     {
750         tx_thread_sleep(NX_IP_PERIODIC_RATE);
751     }
752 
753     generate_device_twin_reported_properties_response(&iot_client);
754 
755     assert_int_not_equal(0xFFFFFFFF, request_id);
756     assert_int_equal(g_response_status, test_dt_reported_properties_response_status);
757 }
758 
759 /**
760  * Test device twin receive twin properties fail if invalid argument is passed.
761  *
762  **/
test_nx_azure_iot_hub_client_device_twin_propetries_request_invalid_argument_failure()763 static VOID test_nx_azure_iot_hub_client_device_twin_propetries_request_invalid_argument_failure()
764 {
765     printf("test starts =>: %s\n", __func__);
766 
767     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_properties_request(NX_NULL, 0),
768                          NX_AZURE_IOT_SUCCESS);
769 }
770 
771 /**
772  * Test device twin receive twin properties fails if publish failed.
773  *
774  **/
test_nx_azure_iot_hub_client_device_twin_propetries_request_publish_failure()775 static VOID test_nx_azure_iot_hub_client_device_twin_propetries_request_publish_failure()
776 {
777 NX_PACKET *packet_ptr;
778 ULONG bytes_copied;
779 
780     printf("test starts =>: %s\n", __func__);
781 
782     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
783     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
784     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
785                      NX_AZURE_IOT_SUCCESS);
786     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_NOT_SUCCESSFUL);
787 
788     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_properties_request(&iot_client, 0),
789                          NX_AZURE_IOT_SUCCESS);
790 }
791 
792 /**
793  * Test device twin receive twin properties succeed.
794  *
795  **/
test_nx_azure_iot_hub_client_device_twin_propetries_request_success()796 static VOID test_nx_azure_iot_hub_client_device_twin_propetries_request_success()
797 {
798 NX_PACKET *packet_ptr;
799 ULONG bytes_copied;
800 
801     printf("test starts =>: %s\n", __func__);
802 
803     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
804     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
805     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
806                      NX_AZURE_IOT_SUCCESS);
807     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_AZURE_IOT_SUCCESS);
808 
809     assert_int_equal(nx_azure_iot_hub_client_device_twin_properties_request(&iot_client, 0),
810                      NX_AZURE_IOT_SUCCESS);
811 
812     generate_device_twin_document_response(&iot_client);
813     assert_int_equal(nx_azure_iot_hub_client_device_twin_properties_receive(&iot_client, &packet_ptr, NX_WAIT_FOREVER),
814                      NX_AZURE_IOT_SUCCESS);
815 
816     assert_int_equal(nx_packet_data_extract_offset(packet_ptr, 0, result_buffer,
817                                                    sizeof(result_buffer), &bytes_copied),
818                      NX_AZURE_IOT_SUCCESS);
819     assert_memory_equal(result_buffer, test_device_twin_document_response_payload, sizeof(test_device_twin_document_response_payload) - 1);
820 
821     nx_packet_release(packet_ptr);
822 }
823 
824 /**
825  * Test device twin receive twin properties succeed with NX_NO_WAIT
826  *
827  **/
test_nx_azure_iot_hub_client_device_twin_propetries_request_no_blocking_success()828 static VOID test_nx_azure_iot_hub_client_device_twin_propetries_request_no_blocking_success()
829 {
830 NX_PACKET *packet_ptr;
831 ULONG bytes_copied;
832 UINT received = 0;
833 
834     printf("test starts =>: %s\n", __func__);
835 
836     assert_int_equal(nx_azure_iot_hub_client_receive_callback_set(&iot_client,
837                                                               NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES,
838                                                               on_receive_callback,
839                                                               (VOID *)&received),
840                      NX_AZURE_IOT_SUCCESS);
841 
842     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
843     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
844     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
845                      NX_AZURE_IOT_SUCCESS);
846     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_AZURE_IOT_SUCCESS);
847 
848     assert_int_equal(nx_azure_iot_hub_client_device_twin_properties_request(&iot_client, 0),
849                      NX_AZURE_IOT_SUCCESS);
850 
851     generate_device_twin_document_response(&iot_client);
852 
853     while (!received)
854     {
855         tx_thread_sleep(NX_IP_PERIODIC_RATE / 10);
856     }
857 
858     assert_int_equal(nx_azure_iot_hub_client_device_twin_properties_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
859                      NX_AZURE_IOT_SUCCESS);
860 
861     assert_int_equal(nx_packet_data_extract_offset(packet_ptr, 0, result_buffer,
862                                                    sizeof(result_buffer), &bytes_copied),
863                      NX_AZURE_IOT_SUCCESS);
864     assert_memory_equal(result_buffer, test_device_twin_document_response_payload, sizeof(test_device_twin_document_response_payload) - 1);
865 
866     nx_packet_release(packet_ptr);
867 }
868 
869 /**
870  * Test device twin receive twin properties fails with allocation fail
871  *
872  **/
test_nx_azure_iot_hub_client_device_twin_propetries_request_allocation_fail_failure()873 static VOID test_nx_azure_iot_hub_client_device_twin_propetries_request_allocation_fail_failure()
874 {
875 UINT total_allocation_in_success_case;
876 UINT status;
877 NX_PACKET *packet_ptr;
878 
879     printf("test starts =>: %s\n", __func__);
880 
881     test_nx_azure_iot_hub_client_device_twin_propetries_request_success();
882     total_allocation_in_success_case = g_total_allocation;
883 
884     for (INT index = 0; index < total_allocation_in_success_case; index++)
885     {
886         reset_global_state();
887         g_failed_allocation_index = index;
888 
889         status = nx_azure_iot_hub_client_device_twin_properties_request(&iot_client, 0);
890 
891         if (status)
892         {
893             continue;
894         }
895 
896         generate_device_twin_document_response(&iot_client);
897         assert_int_not_equal(nx_azure_iot_hub_client_device_twin_properties_receive(&iot_client, &packet_ptr, 0),
898                              NX_AZURE_IOT_SUCCESS);
899     }
900 }
901 
902 /**
903  * Test device twin receive twin desired properties fail with invalid argument.
904  *
905  **/
test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_invalid_argument_failure()906 static VOID test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_invalid_argument_failure()
907 {
908     printf("test starts =>: %s\n", __func__);
909 
910     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_NULL, NX_NULL, NX_WAIT_FOREVER),
911                          NX_AZURE_IOT_SUCCESS);
912 }
913 
914 /**
915  * Test device twin receive twin desired properties succeed.
916  *
917  **/
test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_success()918 static VOID test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_success()
919 {
920 NX_PACKET *packet_ptr;
921 ULONG bytes_copied;
922 
923     printf("test starts =>: %s\n", __func__);
924 
925     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
926     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
927     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
928                      NX_AZURE_IOT_SUCCESS);
929     generate_device_twin_desired_properties_response(&iot_client);
930 
931     assert_int_equal(nx_azure_iot_hub_client_device_twin_desired_properties_receive(&iot_client, &packet_ptr, NX_WAIT_FOREVER),
932                      NX_AZURE_IOT_SUCCESS);
933 
934     assert_int_equal(nx_packet_data_extract_offset(packet_ptr, 0, result_buffer,
935                                                    sizeof(result_buffer), &bytes_copied),
936                      NX_AZURE_IOT_SUCCESS);
937     assert_memory_equal(result_buffer, test_device_twin_desired_properties_response_payload,
938                         sizeof(test_device_twin_desired_properties_response_payload) - 1);
939 
940     nx_packet_release(packet_ptr);
941 }
942 
943 /**
944  * Test device twin receive twin desired properties succeed.
945  *
946  **/
test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_no_blocking_success()947 static VOID test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_no_blocking_success()
948 {
949 NX_PACKET *packet_ptr;
950 ULONG bytes_copied;
951 UINT received = 0;
952 
953     printf("test starts =>: %s\n", __func__);
954 
955     assert_int_equal(nx_azure_iot_hub_client_receive_callback_set(&iot_client,
956                                                                   NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES,
957                                                                   on_receive_callback,
958                                                                   (VOID *)&received),
959                      NX_AZURE_IOT_SUCCESS);
960 
961     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
962     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
963     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
964                      NX_AZURE_IOT_SUCCESS);
965     generate_device_twin_desired_properties_response(&iot_client);
966 
967     while (!received)
968     {
969         tx_thread_sleep(NX_IP_PERIODIC_RATE / 10);
970     }
971 
972     assert_int_equal(nx_azure_iot_hub_client_device_twin_desired_properties_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
973                      NX_AZURE_IOT_SUCCESS);
974 
975     assert_int_equal(nx_packet_data_extract_offset(packet_ptr, 0, result_buffer,
976                                                    sizeof(result_buffer), &bytes_copied),
977                      NX_AZURE_IOT_SUCCESS);
978     assert_memory_equal(result_buffer, test_device_twin_desired_properties_response_payload,
979                         sizeof(test_device_twin_desired_properties_response_payload) - 1);
980 
981     nx_packet_release(packet_ptr);
982 }
983 
984 /**
985  * Test no one is receiving device twin.
986  *
987  **/
test_nx_azure_iot_hub_client_device_twin_no_receive()988 static VOID test_nx_azure_iot_hub_client_device_twin_no_receive()
989 {
990 NX_PACKET *packet_ptr;
991 ULONG bytes_copied;
992 
993     printf("test starts =>: %s\n", __func__);
994 
995     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
996     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
997     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
998                      NX_AZURE_IOT_SUCCESS);
999     generate_device_twin_desired_properties_response(&iot_client);
1000     generate_device_twin_document_response(&iot_client);
1001 }
1002 
1003 /**
1004  * Test invalid argument receiving device twin.
1005  *
1006  **/
test_nx_azure_iot_hub_client_device_twin_receive_invalid_argument_failure()1007 static VOID test_nx_azure_iot_hub_client_device_twin_receive_invalid_argument_failure()
1008 {
1009     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_NULL, NX_NULL, NX_WAIT_FOREVER),
1010                          NX_AZURE_IOT_SUCCESS);
1011 }
1012 
1013 /**
1014  * Test device twin receive twin desired properties fails with allocation fail
1015  *
1016  **/
test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_allocation_fail_failure()1017 static VOID test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_allocation_fail_failure()
1018 {
1019 UINT total_allocation_in_success_case;
1020 UINT status;
1021 NX_PACKET *packet_ptr;
1022 
1023     printf("test starts =>: %s\n", __func__);
1024 
1025     test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_success();
1026     total_allocation_in_success_case = g_total_allocation;
1027 
1028     for (INT index = 0; index < total_allocation_in_success_case; index++)
1029     {
1030         reset_global_state();
1031         g_failed_allocation_index = index;
1032 
1033         generate_device_twin_desired_properties_response(&iot_client);
1034         assert_int_not_equal(nx_azure_iot_hub_client_device_twin_desired_properties_receive(&iot_client, &packet_ptr, NX_WAIT_FOREVER),
1035                              NX_AZURE_IOT_SUCCESS);
1036     }
1037 }
1038 
1039 /**
1040  * Test receive throttling error.
1041  *
1042  **/
test_nx_azure_iot_hub_client_device_twin_propetries_request_throttle()1043 static VOID test_nx_azure_iot_hub_client_device_twin_propetries_request_throttle()
1044 {
1045 NX_PACKET *packet_ptr;
1046 ULONG bytes_copied;
1047 
1048     printf("test starts =>: %s\n", __func__);
1049 
1050     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
1051     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
1052     assert_int_equal(nx_azure_iot_hub_client_device_twin_enable(&iot_client),
1053                      NX_AZURE_IOT_SUCCESS);
1054     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_AZURE_IOT_SUCCESS);
1055 
1056     assert_int_equal(nx_azure_iot_hub_client_device_twin_properties_request(&iot_client, 0),
1057                      NX_AZURE_IOT_SUCCESS);
1058 
1059     generate_device_twin_document_throttled_response(&iot_client);
1060     assert_int_not_equal(nx_azure_iot_hub_client_device_twin_properties_receive(&iot_client, &packet_ptr, 0),
1061                          NX_AZURE_IOT_SUCCESS);
1062     assert_int_equal(nx_azure_iot_hub_client_device_twin_properties_request(&iot_client, 0), NX_AZURE_IOT_THROTTLED);
1063 
1064     will_return(__wrap__nxd_mqtt_client_publish_packet_send, NX_AZURE_IOT_SUCCESS);
1065     while (nx_azure_iot_hub_client_device_twin_properties_request(&iot_client, 0))
1066     {
1067         tx_thread_sleep(NX_IP_PERIODIC_RATE);
1068     }
1069 
1070     generate_device_twin_document_response(&iot_client);
1071     assert_int_equal(nx_azure_iot_hub_client_device_twin_properties_receive(&iot_client, &packet_ptr, 0),
1072                      NX_AZURE_IOT_SUCCESS);
1073 
1074     assert_int_equal(nx_packet_data_extract_offset(packet_ptr, 0, result_buffer,
1075                                                    sizeof(result_buffer), &bytes_copied),
1076                      NX_AZURE_IOT_SUCCESS);
1077     assert_memory_equal(result_buffer, test_device_twin_document_response_payload, sizeof(test_device_twin_document_response_payload) - 1);
1078 
1079     nx_packet_release(packet_ptr);
1080 }
1081 
demo_entry(NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,NX_DNS * dns_ptr,UINT (* unix_time_callback)(ULONG * unix_time))1082 VOID demo_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
1083 {
1084     NX_AZURE_TEST_FN tests[] = { test_nx_azure_iot_hub_client_device_twin_enable_invalid_argument_failure,
1085                                test_nx_azure_iot_hub_client_device_twin_enable_failure,
1086                                test_nx_azure_iot_hub_client_device_twin_enable_success,
1087                                test_nx_azure_iot_hub_client_device_twin_disable_invalid_argument_failure,
1088                                test_nx_azure_iot_hub_client_device_twin_disable_failure,
1089                                test_nx_azure_iot_hub_client_device_twin_disable_success,
1090                                test_nx_azure_iot_hub_client_reported_properties_response_callback_set_invalid_argument_failure,
1091                                test_nx_azure_iot_hub_client_reported_properties_response_callback_set_success,
1092                                test_nx_azure_iot_hub_client_report_properties_response_callback_set_invalid_argument_failure,
1093                                test_nx_azure_iot_hub_client_report_properties_response_callback_set_success,
1094                                test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_invalid_argument_failure,
1095                                test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_publish_failure,
1096                                test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_success,
1097                                test_nx_azure_iot_hub_client_device_twin_reported_propetries_send_throttled,
1098                                test_nx_azure_iot_hub_client_device_twin_propetries_request_invalid_argument_failure,
1099                                test_nx_azure_iot_hub_client_device_twin_propetries_request_publish_failure,
1100                                test_nx_azure_iot_hub_client_device_twin_propetries_request_success,
1101                                test_nx_azure_iot_hub_client_device_twin_propetries_request_no_blocking_success,
1102                                test_nx_azure_iot_hub_client_device_twin_propetries_request_throttle,
1103                                test_nx_azure_iot_hub_client_device_twin_propetries_request_allocation_fail_failure,
1104                                test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_invalid_argument_failure,
1105                                test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_success,
1106                                test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_no_blocking_success,
1107                                test_nx_azure_iot_hub_client_device_twin_no_receive,
1108                                test_nx_azure_iot_hub_client_device_twin_receive_invalid_argument_failure,
1109                                test_nx_azure_iot_hub_client_device_twin_desired_properties_receive_allocation_fail_failure };
1110     INT number_of_tests =  sizeof(tests)/sizeof(tests[0]);
1111     g_ip_ptr = ip_ptr;
1112     g_pool_ptr = pool_ptr;
1113     g_dns_ptr = dns_ptr;
1114 
1115     test_suit_begin();
1116 
1117     printf("Number of tests %d\r\n", number_of_tests);
1118     for (INT index = 0; index < number_of_tests; index++)
1119     {
1120         test_begin();
1121         tests[index]();
1122         test_end();
1123     }
1124 
1125     test_suit_end();
1126 }
1127