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
13 #include "nx_api.h"
14 #include "nx_azure_iot_hub_client.h"
15 #include "nx_azure_iot_cert.h"
16 #include "nx_azure_iot_ciphersuites.h"
17
18
19 #define DEMO_DHCP_DISABLE
20 #define DEMO_IPV4_ADDRESS IP_ADDRESS(192, 168, 100, 33)
21 #define DEMO_IPV4_MASK 0xFFFFFF00UL
22 #define DEMO_GATEWAY_ADDRESS IP_ADDRESS(192, 168, 100, 1)
23 #define DEMO_DNS_SERVER_ADDRESS IP_ADDRESS(192, 168, 100, 1)
24 #define NETWORK_DRIVER _nx_ram_network_driver
25
26 /* Include main.c in the test case since we need to disable DHCP in this test. */
27 #include "main.c"
28
29
30 #define STRING_UNSIGNED_ARGS(s) (UCHAR *)s, strlen(s)
31
32 #ifndef DEMO_CLOUD_STACK_SIZE
33 #define DEMO_CLOUD_STACK_SIZE 2048
34 #endif /* DEMO_CLOUD_STACK_SIZE */
35
36 #ifndef DEMO_CLOUD_THREAD_PRIORITY
37 #define DEMO_CLOUD_THREAD_PRIORITY (4)
38 #endif /* DEMO_CLOUD_THREAD_PRIORITY */
39
40 static VOID connection_status_cb(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, UINT status);
41
42 static NX_AZURE_IOT iot;
43 static NX_AZURE_IOT_HUB_CLIENT iot_client;
44 static NX_SECURE_X509_CERT root_ca_cert;
45 static UCHAR metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE];
46 static ULONG demo_cloud_thread_stack[DEMO_CLOUD_STACK_SIZE / sizeof(ULONG)];
47 extern int g_argc;
48 extern char **g_argv;
49
demo_entry(NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,NX_DNS * dns_ptr,UINT (* unix_time_callback)(ULONG * unix_time))50 VOID demo_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
51 {
52 CHAR *host_name = "host_name";
53 CHAR *device_id = "device_id";
54 CHAR *module_id = "module_id";
55 CHAR *symmetric_key = "symmetric_key";
56 UINT i;
57 ULONG pool_ptr_available_packet;
58
59 /* Initialize root certificate. */
60 assert_int_equal(nx_secure_x509_certificate_initialize(&root_ca_cert, (UCHAR *)_nx_azure_iot_root_cert, (USHORT)_nx_azure_iot_root_cert_size,
61 NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE),
62 NX_AZURE_IOT_SUCCESS);
63
64 assert_int_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
65 sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
66 NX_AZURE_IOT_SUCCESS);
67
68 /* Record number of available packet before test */
69 pool_ptr_available_packet = pool_ptr -> nx_packet_pool_available;
70
71 assert_int_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
72 STRING_UNSIGNED_ARGS(host_name),
73 STRING_UNSIGNED_ARGS(device_id),
74 NX_NULL, 0,
75 _nx_azure_iot_tls_supported_crypto,
76 _nx_azure_iot_tls_supported_crypto_size,
77 _nx_azure_iot_tls_ciphersuite_map,
78 _nx_azure_iot_tls_ciphersuite_map_size,
79 metadata_buffer, sizeof(metadata_buffer),
80 &root_ca_cert),
81 NX_AZURE_IOT_SUCCESS);
82
83 /* Setup callback function. */
84 /* FAIL: NX_AZURE_IOT_HUB_CLIENT pointer is null. */
85 assert_int_not_equal(nx_azure_iot_hub_client_connection_status_callback_set(NX_NULL, connection_status_cb),
86 NX_AZURE_IOT_SUCCESS);
87
88 /* SUCCESS: Setup callback function. */
89 assert_int_equal(nx_azure_iot_hub_client_connection_status_callback_set(&iot_client, connection_status_cb),
90 NX_AZURE_IOT_SUCCESS);
91
92 /* Setup Setup model Id. */
93 /* FAIL: NX_AZURE_IOT_HUB_CLIENT pointer is null. */
94 assert_int_not_equal(nx_azure_iot_hub_client_model_id_set(NX_NULL, STRING_UNSIGNED_ARGS("test::pnp")),
95 NX_AZURE_IOT_SUCCESS);
96
97 /* SUCCESS: Setup model Id. */
98 assert_int_equal(nx_azure_iot_hub_client_model_id_set(&iot_client, STRING_UNSIGNED_ARGS("test::pnp")),
99 NX_AZURE_IOT_SUCCESS);
100
101 /* Setup Setup symmetric key. */
102 /* FAIL: NX_AZURE_IOT_HUB_CLIENT pointer is null. */
103 assert_int_not_equal(nx_azure_iot_hub_client_symmetric_key_set(NX_NULL, STRING_UNSIGNED_ARGS("SGVsbG8gdGhpcyBpcyB0ZXN0")),
104 NX_AZURE_IOT_SUCCESS);
105
106 /* SUCCESS: Setup Setup symmetric key. */
107 assert_int_equal(nx_azure_iot_hub_client_symmetric_key_set(&iot_client, STRING_UNSIGNED_ARGS("SGVsbG8gdGhpcyBpcyB0ZXN0")),
108 NX_AZURE_IOT_SUCCESS);
109
110 /*********** Test nx_azure_iot_hub_client_connect() ***********/
111 /* FAIL: NX_AZURE_IOT_HUB_CLIENT pointer is null. */
112 assert_int_not_equal(nx_azure_iot_hub_client_connect(NX_NULL, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
113 NX_AZURE_IOT_SUCCESS);
114
115 /* FAIL: nx_azure_iot_ptr is null. */
116 iot_client.nx_azure_iot_ptr = NX_NULL;
117 assert_int_not_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
118 NX_AZURE_IOT_SUCCESS);
119 iot_client.nx_azure_iot_ptr = &iot;
120
121 /* FAIL: Invalid value of nx_azure_iot_hub_client_state. */
122 iot_client.nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED;
123 assert_int_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
124 NX_AZURE_IOT_ALREADY_CONNECTED);
125 iot_client.nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTING;
126 assert_int_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
127 NX_AZURE_IOT_CONNECTING);
128 iot_client.nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
129
130 /* FAIL: nxd_dns_host_by_name_get will fail by hijacked function. */
131 will_return(__wrap__nxde_dns_host_by_name_get, NX_DNS_PARAM_ERROR);
132 assert_int_not_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
133 NX_AZURE_IOT_SUCCESS);
134 will_return_always(__wrap__nxde_dns_host_by_name_get, NXD_MQTT_SUCCESS);
135
136 /* TODO: add more test points for packet buffer. */
137
138 /* FAIL: nxd_mqtt_client_secure_connect will fail by hijacked function. */
139 will_return(__wrap__nxde_mqtt_client_secure_connect, NXD_MQTT_INVALID_PARAMETER);
140 expect_value(connection_status_cb, status, NXD_MQTT_INVALID_PARAMETER);
141 assert_int_not_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
142 NX_AZURE_IOT_SUCCESS);
143
144 /* SUCCESS: connected. */
145 will_return_always(__wrap__nxde_mqtt_client_secure_connect, NXD_MQTT_SUCCESS);
146 expect_value(connection_status_cb, status, NX_AZURE_IOT_SUCCESS);
147 assert_int_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
148 NX_AZURE_IOT_SUCCESS);
149
150 /*********** Test nx_azure_iot_hub_client_disconnect() ***********/
151 /* FAIL: NX_AZURE_IOT_HUB_CLIENT pointer is null. */
152 assert_int_not_equal(nx_azure_iot_hub_client_disconnect(NX_NULL), NX_AZURE_IOT_SUCCESS);
153
154 /* FAIL: nxd_mqtt_client_disconnect will fail by hijacked function. */
155 will_return(__wrap__nxde_mqtt_client_disconnect, NXD_MQTT_INVALID_PARAMETER);
156 assert_int_not_equal(nx_azure_iot_hub_client_disconnect(&iot_client), NX_AZURE_IOT_SUCCESS);
157 will_return_always(__wrap__nxde_mqtt_client_disconnect, NXD_MQTT_SUCCESS);
158
159 /* SUCCESS: disconnected. */
160 assert_int_equal(nx_azure_iot_hub_client_disconnect(&iot_client), NX_AZURE_IOT_SUCCESS);
161
162 /* Try reconnect. */
163 expect_value(connection_status_cb, status, NX_AZURE_IOT_SUCCESS);
164 assert_int_equal(nx_azure_iot_hub_client_connect(&iot_client, NX_FALSE, 20 * NX_IP_PERIODIC_RATE),
165 NX_AZURE_IOT_SUCCESS);
166
167 /* SUCCESS: disconnected. */
168 assert_int_equal(nx_azure_iot_hub_client_disconnect(&iot_client), NX_AZURE_IOT_SUCCESS);
169
170 /*********** End Test ***********/
171
172 assert_int_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
173 NX_AZURE_IOT_SUCCESS);
174
175 /* Check if all the packet are released */
176 assert_int_equal(pool_ptr -> nx_packet_pool_available, pool_ptr_available_packet);
177
178 assert_int_equal(nx_azure_iot_delete(&iot), NX_AZURE_IOT_SUCCESS);
179 }
180
__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)181 UINT __wrap__nxde_dns_host_by_name_get(NX_DNS *dns_ptr, UCHAR *host_name, NXD_ADDRESS *host_address_ptr,
182 ULONG wait_option, UINT lookup_type)
183 {
184 UINT status = (UINT)mock();
185
186 printf("HIJACKED: %s\n", __func__);
187 if (status)
188 {
189 return(status);
190 }
191
192 assert_memory_equal(host_name, "host_name", strlen("host_name"));
193 host_address_ptr -> nxd_ip_address.v4 = IP_ADDRESS(127, 0, 0, 1);
194 return(status);
195 }
196
__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)197 UINT __wrap__nxde_mqtt_client_secure_connect(NXD_MQTT_CLIENT *client_ptr, NXD_ADDRESS *server_ip, UINT server_port,
198 UINT (*tls_setup)(NXD_MQTT_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *,
199 NX_SECURE_X509_CERT *, NX_SECURE_X509_CERT *),
200 UINT keepalive, UINT clean_session, ULONG wait_option)
201 {
202 UINT status = (UINT)mock();
203
204 printf("HIJACKED: %s\n", __func__);
205 if (status)
206 {
207 return(status);
208 }
209
210 client_ptr -> nxd_mqtt_client_state = NXD_MQTT_CLIENT_STATE_CONNECTED;
211 return(status);
212 }
213
__wrap__nxde_mqtt_client_disconnect(NXD_MQTT_CLIENT * client_ptr)214 UINT __wrap__nxde_mqtt_client_disconnect(NXD_MQTT_CLIENT *client_ptr)
215 {
216 UINT status = (UINT)mock();
217
218 printf("HIJACKED: %s\n", __func__);
219 if (status)
220 {
221 return(status);
222 }
223 client_ptr -> nxd_mqtt_client_state = NXD_MQTT_CLIENT_STATE_IDLE;
224 return(status);
225 }
226
connection_status_cb(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT * hub_client_ptr,UINT status)227 static VOID connection_status_cb(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, UINT status)
228 {
229 assert_ptr_equal(hub_client_ptr, &iot_client);
230 check_expected(status);
231 }
232
__wrap_nx_azure_iot_security_module_enable(NX_AZURE_IOT * nx_azure_iot_ptr)233 UINT __wrap_nx_azure_iot_security_module_enable(NX_AZURE_IOT *nx_azure_iot_ptr)
234 {
235 printf("HIJACKED: %s\n", __func__);
236 return(NX_AZURE_IOT_SUCCESS);
237 }
238
__wrap_nx_azure_iot_security_module_disable(NX_AZURE_IOT * nx_azure_iot_ptr)239 UINT __wrap_nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr)
240 {
241 printf("HIJACKED: %s\n", __func__);
242 return(NX_AZURE_IOT_SUCCESS);
243 }
244