1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <string.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/init.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/net_buf.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
15 #include <zephyr/mgmt/mcumgr/smp/smp.h>
16 #include <zephyr/mgmt/mcumgr/smp/smp_client.h>
17 #include <zephyr/mgmt/mcumgr/transport/smp.h>
18 #include <mgmt/mcumgr/transport/smp_internal.h>
19 #include "smp_transport_stub.h"
20 
21 static struct net_buf *buf[5];
22 
23 static uint32_t testing_user_data;
24 static void *response_ptr;
25 static struct net_buf *res_buf;
26 static struct smp_client_object smp_client;
27 
smp_client_res_cb(struct net_buf * nb,void * user_data)28 int smp_client_res_cb(struct net_buf *nb, void *user_data)
29 {
30 	res_buf = nb;
31 	response_ptr = user_data;
32 	return 0;
33 }
34 
ZTEST(smp_client,test_buf_alloc)35 ZTEST(smp_client, test_buf_alloc)
36 {
37 	struct smp_client_object smp_client;
38 
39 	/* Allocate all 4 buffer's and verify that 5th fail */
40 	for (int i = 0; i < 5; i++) {
41 		buf[i] = smp_client_buf_allocation(&smp_client, MGMT_GROUP_ID_IMAGE, 1,
42 						   MGMT_OP_WRITE, SMP_MCUMGR_VERSION_1);
43 		if (i == 4) {
44 			zassert_is_null(buf[i], "Buffer was not Null");
45 		} else {
46 			zassert_not_null(buf[i], "Buffer was Null");
47 			zassert_equal(sizeof(struct smp_hdr), buf[i]->len,
48 				      "Expected to receive %d response %d",
49 				      sizeof(struct smp_hdr), buf[i]->len);
50 		}
51 	}
52 
53 	for (int i = 0; i < 4; i++) {
54 		smp_client_buf_free(buf[i]);
55 		buf[i] = NULL;
56 	}
57 }
58 
ZTEST(smp_client,test_msg_send_timeout)59 ZTEST(smp_client, test_msg_send_timeout)
60 {
61 	struct net_buf *nb;
62 
63 	int rc;
64 
65 	nb = smp_client_buf_allocation(&smp_client, MGMT_GROUP_ID_IMAGE, 1, MGMT_OP_WRITE,
66 				       SMP_MCUMGR_VERSION_1);
67 	zassert_not_null(nb, "Buffer was Null");
68 	rc = smp_client_send_cmd(&smp_client, nb, smp_client_res_cb, &testing_user_data, 2);
69 	zassert_equal(MGMT_ERR_EOK, rc, "Expected to receive %d response %d", MGMT_ERR_EOK, rc);
70 	k_sleep(K_SECONDS(3));
71 	zassert_is_null(res_buf, "NULL pointer was not returned");
72 	zassert_equal_ptr(response_ptr, &testing_user_data, "User data not returned correctly");
73 }
74 
ZTEST(smp_client,test_msg_response_handler)75 ZTEST(smp_client, test_msg_response_handler)
76 {
77 	struct smp_hdr dst_hdr;
78 	int rc;
79 
80 
81 	response_ptr = NULL;
82 	res_buf = NULL;
83 
84 	buf[0] = smp_client_buf_allocation(&smp_client, MGMT_GROUP_ID_IMAGE, 1, MGMT_OP_WRITE,
85 					   SMP_MCUMGR_VERSION_1);
86 	zassert_not_null(buf[0], "Buffer was Null");
87 	rc = smp_client_send_cmd(&smp_client, buf[0], smp_client_res_cb, &testing_user_data, 8);
88 	zassert_equal(MGMT_ERR_EOK, rc, "Expected to receive %d response %d", MGMT_ERR_EOK, rc);
89 	buf[1] = smp_client_buf_allocation(&smp_client, MGMT_GROUP_ID_IMAGE, 1, MGMT_OP_WRITE,
90 					   SMP_MCUMGR_VERSION_1);
91 	zassert_not_null(buf[0], "Buffer was Null");
92 	/* Read Pushed packet Header */
93 	smp_transport_read_hdr(buf[0], &dst_hdr);
94 	smp_client_single_response(buf[1], &dst_hdr);
95 	zassert_is_null(res_buf, "NULL pointer was not returned");
96 	zassert_is_null(response_ptr, "NULL pointer was not returned");
97 	/* Set Correct OP */
98 	dst_hdr.nh_op = MGMT_OP_WRITE_RSP;
99 	smp_client_single_response(buf[1], &dst_hdr);
100 	zassert_equal_ptr(res_buf, buf[1], "Response Buf not correct");
101 	zassert_equal_ptr(response_ptr, &testing_user_data, "User data not returned correctly");
102 	response_ptr = NULL;
103 	res_buf = NULL;
104 	smp_client_single_response(buf[1], &dst_hdr);
105 	zassert_is_null(res_buf, "NULL pointer was not returned");
106 	zassert_is_null(response_ptr, "NULL pointer was not returned");
107 }
108 
setup_custom_os(void)109 static void *setup_custom_os(void)
110 {
111 	/* Registre tarnsport and init client */
112 	stub_smp_client_transport_register();
113 	smp_client_object_init(&smp_client, SMP_SERIAL_TRANSPORT);
114 	return NULL;
115 }
116 
cleanup_test(void * p)117 static void cleanup_test(void *p)
118 {
119 	for (int i = 0; i < 5; i++) {
120 		if (buf[i]) {
121 			smp_client_buf_free(buf[i]);
122 			buf[i] = NULL;
123 		}
124 	}
125 }
126 
127 /* Main test set */
128 ZTEST_SUITE(smp_client, NULL, setup_custom_os, NULL, cleanup_test, NULL);
129