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 #define C2D_TOPIC                 "devices/device_id/messages/devicebound/"
32 
33 #define CALLBACK_ARGS             0x12345678
34 
35 #define STRING_UNSIGNED_ARGS(s) (UCHAR *)s, strlen(s)
36 
37 #ifndef DEMO_CLOUD_STACK_SIZE
38 #define DEMO_CLOUD_STACK_SIZE   2048
39 #endif /* DEMO_CLOUD_STACK_SIZE */
40 
41 #ifndef DEMO_CLOUD_THREAD_PRIORITY
42 #define DEMO_CLOUD_THREAD_PRIORITY  (4)
43 #endif /* DEMO_CLOUD_THREAD_PRIORITY */
44 
45 #ifndef MAXIMUM_PROPERTY_LENGTH
46 #define MAXIMUM_PROPERTY_LENGTH 1400 /* packet size */
47 #endif /* MAXIMUM_PROPERTY_LENGTH */
48 
49 #ifndef MAXIMUM_PAYLOAD_LENGTH
50 #define MAXIMUM_PAYLOAD_LENGTH 10240
51 #endif /* MAXIMUM_PAYLOAD_LENGTH */
52 
53 #define MQTT_CLIENT_GET(c)              ((c) -> nx_azure_iot_hub_client_resource.resource_mqtt)
54 #define TX_MUTEX_GET(c)                 ((c) -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr)
55 
56 typedef struct
57 {
58     UCHAR *name;
59     ULONG name_length;
60     UCHAR *value;
61     ULONG value_length;
62 } PROPERTY;
63 
64 #define PROPERTY_INIT(name, value) {(name), sizeof(name) - 1, (value), sizeof(value) - 1}
65 
66 static VOID initialize_data();
67 static VOID property_payload_test(UINT packet_offset);
68 static VOID callback_test();
69 static VOID invalid_packet_test();
70 static VOID wait_timeout_test();
71 static VOID no_receiver_test();
72 static VOID construct_c2d_packet(NX_PACKET **packet_pptr, PROPERTY *properties, UINT property_count,
73                                  UCHAR *message_payload_ptr, ULONG message_payload_length,
74                                  UINT packet_offset);
75 static VOID c2d_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *args);
76 extern UINT _nxd_mqtt_client_append_message(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, CHAR *message,
77                                             UINT length, ULONG wait_option);
78 extern UINT _nxd_mqtt_client_set_fixed_header(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr,
79                                               UCHAR control_header, UINT length, UINT wait_option);
80 
81 static NX_AZURE_IOT iot;
82 static NX_AZURE_IOT_HUB_CLIENT iot_client;
83 static NX_SECURE_X509_CERT root_ca_cert;
84 static UCHAR metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE];
85 static ULONG demo_cloud_thread_stack[DEMO_CLOUD_STACK_SIZE / sizeof(ULONG)];
86 static UCHAR property_name[MAXIMUM_PROPERTY_LENGTH];
87 static UCHAR property_value[MAXIMUM_PROPERTY_LENGTH];
88 static UCHAR message_payload[MAXIMUM_PAYLOAD_LENGTH];
89 static UCHAR result_buffer[MAXIMUM_PAYLOAD_LENGTH];
90 static VOID (*test_receive_notify)(NXD_MQTT_CLIENT *client_ptr, UINT message_count) = NX_NULL;
91 
demo_entry(NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,NX_DNS * dns_ptr,UINT (* unix_time_callback)(ULONG * unix_time))92 VOID demo_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
93 {
94 CHAR *host_name = "host_name";
95 CHAR *device_id = "device_id";
96 CHAR *module_id = "module_id";
97 CHAR *symmetric_key = "symmetric_key";
98 ULONG pool_ptr_available_packet;
99 
100     /* Initialize root certificate.  */
101     assert_int_equal(nx_secure_x509_certificate_initialize(&root_ca_cert, (UCHAR *)_nx_azure_iot_root_cert, (USHORT)_nx_azure_iot_root_cert_size,
102                                                            NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE),
103                      NX_AZURE_IOT_SUCCESS);
104 
105     assert_int_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
106                                          sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
107                      NX_AZURE_IOT_SUCCESS);
108 
109     /* Record number of available packet before test */
110     pool_ptr_available_packet = pool_ptr -> nx_packet_pool_available;
111 
112     assert_int_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
113                                                         STRING_UNSIGNED_ARGS(host_name),
114                                                         STRING_UNSIGNED_ARGS(device_id),
115                                                         STRING_UNSIGNED_ARGS(""),
116                                                         _nx_azure_iot_tls_supported_crypto,
117                                                         _nx_azure_iot_tls_supported_crypto_size,
118                                                         _nx_azure_iot_tls_ciphersuite_map,
119                                                         _nx_azure_iot_tls_ciphersuite_map_size,
120                                                         metadata_buffer, sizeof(metadata_buffer),
121                                                         &root_ca_cert),
122                      NX_AZURE_IOT_SUCCESS);
123 
124     assert_int_equal(nx_azure_iot_hub_client_cloud_message_enable(&iot_client),
125                      NX_AZURE_IOT_SUCCESS);
126 
127     will_return(__wrap__nxde_mqtt_client_subscribe, NX_AZURE_IOT_SUCCESS);
128     /* Connect IoTHub client */
129     assert_int_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, NX_WAIT_FOREVER),
130                      NX_AZURE_IOT_SUCCESS);
131 
132     /* Perform actual tests. */
133     initialize_data();
134     property_payload_test(0);
135     property_payload_test(1000);
136     callback_test();
137     invalid_packet_test();
138     wait_timeout_test();
139     no_receiver_test();
140 
141 
142     will_return(__wrap__nxde_mqtt_client_unsubscribe, NX_AZURE_IOT_SUCCESS);
143     assert_int_equal(nx_azure_iot_hub_client_cloud_message_disable(&iot_client),
144                      NX_AZURE_IOT_SUCCESS);
145 
146     assert_int_equal(nx_azure_iot_hub_client_disconnect(&iot_client),
147                      NX_AZURE_IOT_SUCCESS);
148 
149     assert_int_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
150                      NX_AZURE_IOT_SUCCESS);
151 
152     /* Check if all the packet are released */
153     assert_int_equal(pool_ptr -> nx_packet_pool_available, pool_ptr_available_packet);
154 
155     assert_int_equal(nx_azure_iot_delete(&iot), NX_AZURE_IOT_SUCCESS);
156 }
157 
initialize_data()158 static VOID initialize_data()
159 {
160 UINT i;
161 
162     for (i = 0; i < MAXIMUM_PROPERTY_LENGTH; i++)
163     {
164         property_name[i] = (NX_RAND() % 26) + 'a';
165         property_value[i] = (NX_RAND() % 26) + 'a';
166     }
167 
168     for (i = 0; i < sizeof(message_payload); i++)
169     {
170         message_payload[i] = (NX_RAND() % 26) + 'a';
171     }
172 }
173 
construct_c2d_packet(NX_PACKET ** packet_pptr,PROPERTY * properties,UINT property_count,UCHAR * message_payload_ptr,ULONG message_payload_length,UINT packet_offset)174 static VOID construct_c2d_packet(NX_PACKET **packet_pptr, PROPERTY *properties, UINT property_count,
175                                  UCHAR *message_payload_ptr, ULONG message_payload_length, UINT packet_offset)
176 {
177 NX_PACKET *packet_ptr;
178 ULONG topic_length = sizeof(C2D_TOPIC) - 1;
179 ULONG total_length;
180 UCHAR bytes[2];
181 UINT i;
182 
183     assert_int_equal(nx_packet_allocate(iot.nx_azure_iot_pool_ptr, &packet_ptr, packet_offset, NX_NO_WAIT),
184                      NX_AZURE_IOT_SUCCESS);
185 
186     for (i = 0; i < property_count; i++)
187     {
188         topic_length += properties[i].name_length + properties[i].value_length + 2; /* '=' and '&' */
189     }
190 
191     if (property_count)
192     {
193         topic_length--; /* Reduce by one since last '&' is not needed. */
194     }
195     total_length = topic_length + 2 + 2 + message_payload_length; /* Two bytes for fixed topic_length field
196                                                                      and two bytes for packet id. */
197 
198     /* Set fixed header. */
199     assert_int_equal(_nxd_mqtt_client_set_fixed_header(&(MQTT_CLIENT_GET(&iot_client)), packet_ptr,
200                                                        (UCHAR)((MQTT_CONTROL_PACKET_TYPE_PUBLISH << 4) | MQTT_PUBLISH_QOS_LEVEL_1),
201                                                        total_length, NX_NO_WAIT),
202                      NX_AZURE_IOT_SUCCESS);
203 
204     /* Set topic length. */
205     bytes[0] = (topic_length >> 8) & 0xFF;
206     bytes[1] = topic_length & 0xFF;
207     assert_int_equal(nx_packet_data_append(packet_ptr, bytes, sizeof(bytes),
208                                            iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
209                      NX_AZURE_IOT_SUCCESS);
210 
211     /* Set topic. */
212     assert_int_equal(nx_packet_data_append(packet_ptr, C2D_TOPIC, sizeof(C2D_TOPIC) - 1,
213                                            iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
214                      NX_AZURE_IOT_SUCCESS);
215     for (i = 0; i < property_count; i++)
216     {
217         if (i != 0)
218         {
219             assert_int_equal(nx_packet_data_append(packet_ptr, "&", 1,
220                                                    iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
221                              NX_AZURE_IOT_SUCCESS);
222         }
223         assert_int_equal(nx_packet_data_append(packet_ptr, properties[i].name, properties[i].name_length,
224                                                iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
225                          NX_AZURE_IOT_SUCCESS);
226         assert_int_equal(nx_packet_data_append(packet_ptr, "=", 1,
227                                                iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
228                          NX_AZURE_IOT_SUCCESS);
229         assert_int_equal(nx_packet_data_append(packet_ptr, properties[i].value, properties[i].value_length,
230                                                iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
231                          NX_AZURE_IOT_SUCCESS);
232     }
233 
234     /* Set packet ID. The value does not matter. */
235     assert_int_equal(nx_packet_data_append(packet_ptr, bytes, sizeof(bytes),
236                                            iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
237                      NX_AZURE_IOT_SUCCESS);
238 
239     /* Set message payload. */
240     if (message_payload_length > 0)
241     {
242         assert_int_equal(nx_packet_data_append(packet_ptr, message_payload_ptr, message_payload_length,
243                                                iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
244                          NX_AZURE_IOT_SUCCESS);
245     }
246 
247     *packet_pptr = packet_ptr;
248 }
249 
property_payload_test(UINT packet_offset)250 static VOID property_payload_test(UINT packet_offset)
251 {
252 NX_PACKET *packet_ptr;
253 ULONG bytes_copied;
254 USHORT result_size;
255 const UCHAR *result;
256 PROPERTY property = {property_name, 10, property_value, 10};
257 ULONG message_payload_length;
258 ULONG *length;
259 ULONG loop;
260 UINT i;
261 
262     for (i = 0; i < 3; i++)
263     {
264         if (i == 0)
265         {
266 
267             /* First round, length of property name is variable. */
268             loop = MAXIMUM_PROPERTY_LENGTH;
269             length = &property.name_length;
270             property.value_length = 10;
271             message_payload_length = 10;
272         }
273         else if (i == 1)
274         {
275 
276             /* Second round, length of property value is variable. */
277             loop = MAXIMUM_PROPERTY_LENGTH;
278             length = &property.value_length;
279             property.name_length = 10;
280             message_payload_length = 10;
281         }
282         else
283         {
284 
285             /* Third round, length of message is variable. */
286             loop = MAXIMUM_PAYLOAD_LENGTH; /* It is supported when message is spanned in multiple packets. */
287             length = &message_payload_length;
288             property.name_length = 10;
289             property.value_length = 10;
290         }
291         for (*length = 0; *length < loop; (*length)++)
292         {
293             if ((i < 2) && (*length == 0))
294             {
295 
296                 /* Skip length 0 for property. */
297                 continue;
298             }
299 
300             construct_c2d_packet(&packet_ptr, &property, 1, message_payload, message_payload_length, packet_offset);
301 
302             /* Simulate callback from MQTT layer.  */
303             MQTT_CLIENT_GET(&iot_client).message_receive_queue_head = packet_ptr;
304             MQTT_CLIENT_GET(&iot_client).message_receive_queue_depth = 1;
305             tx_mutex_get(TX_MUTEX_GET(&iot_client), NX_WAIT_FOREVER);
306             test_receive_notify(&(MQTT_CLIENT_GET(&iot_client)), 1);
307             tx_mutex_put(TX_MUTEX_GET(&iot_client));
308 
309             assert_int_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
310                              NX_AZURE_IOT_SUCCESS);
311 
312             /* Validate property. */
313             memset(result_buffer, property.value_length, 0);
314             assert_int_equal(nx_azure_iot_hub_client_cloud_message_property_get(&iot_client, packet_ptr,
315                                                                                 property.name, property.name_length,
316                                                                                 &result, &result_size),
317                              NX_AZURE_IOT_SUCCESS);
318             assert_int_equal(property.value_length, result_size);
319             assert_memory_equal(property.value, result, result_size);
320 
321             /* Validate payload. */
322             memset(result_buffer, message_payload_length, 0);
323             assert_int_equal(nx_packet_data_extract_offset(packet_ptr, 0, result_buffer,
324                                                            sizeof(result_buffer), &bytes_copied),
325                              NX_AZURE_IOT_SUCCESS);
326             assert_int_equal(message_payload_length, bytes_copied);
327             assert_memory_equal(message_payload, result_buffer, bytes_copied);
328 
329             nx_packet_release(packet_ptr);
330         }
331     }
332 }
333 
334 static UINT (*c2d_message_process)(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr,
335                                    NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length);
336 
callback_test()337 static VOID callback_test()
338 {
339 ULONG arg = CALLBACK_ARGS;
340 NX_PACKET *packet_ptr;
341 ULONG bytes_copied;
342 ULONG message_payload_length = 10;
343 UINT c2d_control_flag;
344 
345     /* Expected fail: NX_AZURE_IOT_HUB_CLIENT is NULL. */
346     assert_int_not_equal(nx_azure_iot_hub_client_receive_callback_set(NX_NULL,
347                                                                       NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE,
348                                                                       c2d_callback,
349                                                                       &arg),
350                          NX_AZURE_IOT_SUCCESS);
351 
352     /* Expected fail: unknown message type. */
353     assert_int_not_equal(nx_azure_iot_hub_client_receive_callback_set(&iot_client,
354                                                                       0xFFFFFFFF,
355                                                                       c2d_callback,
356                                                                       &arg),
357                          NX_AZURE_IOT_SUCCESS);
358 
359     /* Expect c2d_callback to be called once. */
360     expect_function_calls(c2d_callback, 1);
361 
362     /* Set callback function. */
363     assert_int_equal(nx_azure_iot_hub_client_receive_callback_set(&iot_client,
364                                                                   NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE,
365                                                                   c2d_callback,
366                                                                   &arg),
367                      NX_AZURE_IOT_SUCCESS);
368 
369     /* Put C2D packet to MQTT receive queue.  */
370     construct_c2d_packet(&packet_ptr, NX_NULL, 0, message_payload, message_payload_length, 0);
371     MQTT_CLIENT_GET(&iot_client).message_receive_queue_head = packet_ptr;
372     MQTT_CLIENT_GET(&iot_client).message_receive_queue_depth = 1;
373 
374     /* Expected callback function to be set. */
375     assert_ptr_not_equal(test_receive_notify, NX_NULL);
376 
377     /* Simulate callback from MQTT layer.  */
378     tx_mutex_get(TX_MUTEX_GET(&iot_client), NX_WAIT_FOREVER);
379     test_receive_notify(&(MQTT_CLIENT_GET(&iot_client)), 1);
380     tx_mutex_put(TX_MUTEX_GET(&iot_client));
381 
382     /* Expected fail: NX_AZURE_IOT_HUB_CLIENT is NULL. */
383     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(NX_NULL, &packet_ptr, NX_NO_WAIT),
384                          NX_AZURE_IOT_SUCCESS);
385 
386     /* Expected fail: packet pointer is NULL. */
387     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, NX_NULL, NX_NO_WAIT),
388                          NX_AZURE_IOT_SUCCESS);
389 
390     /* Expected fail: packet pointer is NULL. */
391     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, NX_NULL, NX_NO_WAIT),
392                          NX_AZURE_IOT_SUCCESS);
393 
394     /* Expected fail: message_process is NULL. */
395     c2d_message_process = iot_client.nx_azure_iot_hub_client_c2d_message.message_process;
396     iot_client.nx_azure_iot_hub_client_c2d_message.message_process = NX_NULL;
397     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
398                          NX_AZURE_IOT_SUCCESS);
399     iot_client.nx_azure_iot_hub_client_c2d_message.message_process = c2d_message_process;
400 
401     /* Receive packet by API. */
402     assert_int_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
403                      NX_AZURE_IOT_SUCCESS);
404 
405     /* Validate payload. */
406     memset(result_buffer, message_payload_length, 0);
407     assert_int_equal(nx_packet_data_extract_offset(packet_ptr, 0, result_buffer,
408                                                    sizeof(result_buffer), &bytes_copied),
409                      NX_AZURE_IOT_SUCCESS);
410     assert_int_equal(message_payload_length, bytes_copied);
411     assert_memory_equal(message_payload, result_buffer, bytes_copied);
412     nx_packet_release(packet_ptr);
413 
414     /* Expected fail: no packet available. */
415     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
416                          NX_AZURE_IOT_SUCCESS);
417 
418     /* Clear C2D callback function. */
419     assert_int_equal(nx_azure_iot_hub_client_receive_callback_set(&iot_client,
420                                                                   NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE,
421                                                                   NX_NULL,
422                                                                   NX_NULL),
423                      NX_AZURE_IOT_SUCCESS);
424 }
425 
invalid_packet_test()426 static VOID invalid_packet_test()
427 {
428 NX_PACKET *packet_ptr;
429 UCHAR bytes[2] = {0, 0};
430 
431     assert_int_equal(nx_packet_allocate(iot.nx_azure_iot_pool_ptr, &packet_ptr, 0, NX_NO_WAIT),
432                      NX_AZURE_IOT_SUCCESS);
433     assert_int_equal(nx_packet_data_append(packet_ptr, bytes, sizeof(bytes),
434                                            iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
435                      NX_AZURE_IOT_SUCCESS);
436 
437     /* Put invalid packet to MQTT receive queue.  */
438     MQTT_CLIENT_GET(&iot_client).message_receive_queue_head = packet_ptr;
439     MQTT_CLIENT_GET(&iot_client).message_receive_queue_depth = 1;
440 
441     /* Simulate callback from MQTT layer.  */
442     tx_mutex_get(TX_MUTEX_GET(&iot_client), NX_WAIT_FOREVER);
443     test_receive_notify(&(MQTT_CLIENT_GET(&iot_client)), 1);
444     tx_mutex_put(TX_MUTEX_GET(&iot_client));
445 
446     /* Expected fail: no packet available. */
447     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
448                          NX_AZURE_IOT_SUCCESS);
449 
450 
451     assert_int_equal(nx_packet_allocate(iot.nx_azure_iot_pool_ptr, &packet_ptr, 0, NX_NO_WAIT),
452                      NX_AZURE_IOT_SUCCESS);
453     assert_int_equal(nx_packet_data_append(packet_ptr, bytes, sizeof(bytes),
454                                            iot.nx_azure_iot_pool_ptr, NX_NO_WAIT),
455                      NX_AZURE_IOT_SUCCESS);
456 
457     /* Put invalid packet to receive header. */
458     iot_client.nx_azure_iot_hub_client_c2d_message.message_head = packet_ptr;
459 
460     /* Expected fail: no packet available. */
461     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
462                          NX_AZURE_IOT_SUCCESS);
463 }
464 
wait_timeout_test()465 static VOID wait_timeout_test()
466 {
467 NX_PACKET *packet_ptr;
468 ULONG message_payload_length = 10;
469 
470     /* Expect fail: no packet available. */
471     assert_int_not_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, 1),
472                          NX_AZURE_IOT_SUCCESS);
473 
474     /* Put C2D packet to MQTT receive queue.  */
475     construct_c2d_packet(&packet_ptr, NX_NULL, 0, message_payload, message_payload_length, 0);
476     MQTT_CLIENT_GET(&iot_client).message_receive_queue_head = packet_ptr;
477     MQTT_CLIENT_GET(&iot_client).message_receive_queue_depth = 1;
478 
479     /* Simulate callback from MQTT layer.  */
480     tx_mutex_get(TX_MUTEX_GET(&iot_client), NX_WAIT_FOREVER);
481     test_receive_notify(&(MQTT_CLIENT_GET(&iot_client)), 1);
482     tx_mutex_put(TX_MUTEX_GET(&iot_client));
483 
484     /* Receive packet by API. */
485     assert_int_equal(nx_azure_iot_hub_client_cloud_message_receive(&iot_client, &packet_ptr, NX_NO_WAIT),
486                      NX_AZURE_IOT_SUCCESS);
487     nx_packet_release(packet_ptr);
488 }
489 
no_receiver_test()490 static VOID no_receiver_test()
491 {
492 NX_PACKET *packet_ptr;
493 ULONG message_payload_length = 10;
494 
495     /* Put C2D packet to MQTT receive queue.  */
496     construct_c2d_packet(&packet_ptr, NX_NULL, 0, message_payload, message_payload_length, 0);
497     MQTT_CLIENT_GET(&iot_client).message_receive_queue_head = packet_ptr;
498     MQTT_CLIENT_GET(&iot_client).message_receive_queue_depth = 1;
499 
500     /* Simulate callback from MQTT layer.  */
501     tx_mutex_get(TX_MUTEX_GET(&iot_client), NX_WAIT_FOREVER);
502     test_receive_notify(&(MQTT_CLIENT_GET(&iot_client)), 1);
503     tx_mutex_put(TX_MUTEX_GET(&iot_client));
504 
505     /* No one will receive this packet. Packet leak will be checked at last step of test. */
506 }
507 
c2d_callback(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,VOID * args)508 static VOID c2d_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *args)
509 {
510     function_called();
511     assert_ptr_equal(hub_client_ptr, &iot_client);
512     assert_int_equal(*(ULONG *)args, CALLBACK_ARGS);
513 }
514 
__wrap__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT * client_ptr,VOID (* receive_notify)(NXD_MQTT_CLIENT * client_ptr,UINT message_count))515 UINT __wrap__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT *client_ptr,
516                                                  VOID (*receive_notify)(NXD_MQTT_CLIENT *client_ptr, UINT message_count))
517 {
518     printf("HIJACKED: %s\n", __func__);
519     test_receive_notify = receive_notify;
520     return(NX_AZURE_IOT_SUCCESS);
521 }
522 
__wrap__nxde_mqtt_client_subscribe(NXD_MQTT_CLIENT * client_ptr,UINT op,CHAR * topic_name,UINT topic_name_length,USHORT * packet_id_ptr,UINT QoS)523 UINT __wrap__nxde_mqtt_client_subscribe(NXD_MQTT_CLIENT *client_ptr, UINT op,
524                                         CHAR *topic_name, UINT topic_name_length,
525                                         USHORT *packet_id_ptr, UINT QoS)
526 {
527     printf("HIJACKED: %s\n", __func__);
528     return((UINT)mock());
529 }
530 
__wrap__nxde_mqtt_client_unsubscribe(NXD_MQTT_CLIENT * client_ptr,CHAR * topic_name,UINT topic_name_length,UINT QoS)531 UINT __wrap__nxde_mqtt_client_unsubscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name,
532                                           UINT topic_name_length, UINT QoS)
533 {
534     printf("HIJACKED: %s\n", __func__);
535     return((UINT)mock());
536 }
537 
__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)538 UINT __wrap__nxde_mqtt_client_secure_connect(NXD_MQTT_CLIENT *client_ptr, NXD_ADDRESS *server_ip, UINT server_port,
539                                              UINT (*tls_setup)(NXD_MQTT_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *,
540                                                                NX_SECURE_X509_CERT *, NX_SECURE_X509_CERT *),
541                                              UINT keepalive, UINT clean_session, ULONG wait_option)
542 {
543     printf("HIJACKED: %s\n", __func__);
544 
545     tx_thread_suspend(&(iot.nx_azure_iot_ip_ptr -> nx_ip_thread));
546     client_ptr -> nxd_mqtt_client_state = NXD_MQTT_CLIENT_STATE_CONNECTED;
547     client_ptr -> nxd_mqtt_client_packet_identifier = 1;
548     client_ptr -> nxd_mqtt_tls_session.nx_secure_tls_id = NX_SECURE_TLS_ID;
549     client_ptr -> nxd_mqtt_tls_session.nx_secure_tls_local_session_active = NX_FALSE;
550     client_ptr -> nxd_mqtt_tls_session.nx_secure_tls_tcp_socket = &client_ptr -> nxd_mqtt_client_socket;
551     client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_connect_ip.nxd_ip_version = NX_IP_VERSION_V4;
552     client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_state = NX_TCP_ESTABLISHED;
553 
554     return(NXD_MQTT_SUCCESS);
555 }
556 
__wrap__nxde_mqtt_client_disconnect(NXD_MQTT_CLIENT * client_ptr)557 UINT __wrap__nxde_mqtt_client_disconnect(NXD_MQTT_CLIENT *client_ptr)
558 {
559     printf("HIJACKED: %s\n", __func__);
560     client_ptr -> nxd_mqtt_client_state = NXD_MQTT_CLIENT_STATE_IDLE;
561     client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_state = NX_TCP_CLOSED;
562     return(NXD_MQTT_SUCCESS);
563 }
564 
__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)565 UINT __wrap__nxde_dns_host_by_name_get(NX_DNS *dns_ptr, UCHAR *host_name, NXD_ADDRESS *host_address_ptr,
566                                        ULONG wait_option, UINT lookup_type)
567 {
568     printf("HIJACKED: %s\n", __func__);
569     host_address_ptr -> nxd_ip_address.v4 = IP_ADDRESS(127, 0, 0, 1);
570     return(NX_DNS_SUCCESS);
571 }
572 
__wrap_nx_azure_iot_security_module_enable(NX_AZURE_IOT * nx_azure_iot_ptr)573 UINT __wrap_nx_azure_iot_security_module_enable(NX_AZURE_IOT *nx_azure_iot_ptr)
574 {
575     printf("HIJACKED: %s\n", __func__);
576     return(NX_AZURE_IOT_SUCCESS);
577 }
578 
__wrap_nx_azure_iot_security_module_disable(NX_AZURE_IOT * nx_azure_iot_ptr)579 UINT __wrap_nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr)
580 {
581     printf("HIJACKED: %s\n", __func__);
582     return(NX_AZURE_IOT_SUCCESS);
583 }
584