1 /*
2  * Copyright (c) 2021 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Test log links
10  *
11  */
12 
13 #include <zephyr/tc_util.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/ztest.h>
16 #include <zephyr/logging/log_backend.h>
17 #include <zephyr/logging/log_ctrl.h>
18 #include <zephyr/logging/log_link.h>
19 #include <zephyr/logging/log.h>
20 #include <stdbool.h>
21 
22 LOG_MODULE_REGISTER(test);
23 
24 static log_timestamp_t timestamp;
25 
process(const struct log_backend * const backend,union log_msg_generic * msg)26 static void process(const struct log_backend *const backend,
27 			union log_msg_generic *msg)
28 {
29 
30 }
31 
panic(const struct log_backend * const backend)32 static void panic(const struct log_backend *const backend)
33 {
34 
35 }
36 
37 const struct log_backend_api log_backend_test_api = {
38 	.process = process,
39 	.panic = panic
40 };
41 
42 LOG_BACKEND_DEFINE(backend1, log_backend_test_api, false);
43 
timestamp_get(void)44 static log_timestamp_t timestamp_get(void)
45 {
46 	return timestamp++;
47 }
48 
log_setup(void)49 static void log_setup(void)
50 {
51 	uint8_t offset = 0;
52 	int err;
53 
54 	log_init();
55 
56 	timestamp = 0;
57 	err = log_set_timestamp_func(timestamp_get, 0);
58 	zassert_equal(err, 0, NULL);
59 
60 	(void)z_log_links_activate(0xFFFFFFFF, &offset);
61 
62 	log_backend_enable(&backend1, NULL, LOG_LEVEL_DBG);
63 }
64 
65 extern struct log_link_api mock_log_link_api;
66 
67 LOG_LINK_DEF(mock_link1, mock_log_link_api, 0, NULL);
68 LOG_LINK_DEF(mock_link2, mock_log_link_api, 512, NULL);
69 LOG_LINK_DEF(mock_link3, mock_log_link_api, 1024, NULL);
70 
check_msg(int exp_timestamp,int line)71 static void check_msg(int exp_timestamp, int line)
72 {
73 	union log_msg_generic *msg;
74 	k_timeout_t t;
75 
76 	msg = z_log_msg_claim(&t);
77 
78 	if (exp_timestamp < 0) {
79 		zassert_equal(msg, NULL, "%d: Unexpected msg", line);
80 		return;
81 	}
82 
83 	zassert_true(msg != NULL, "%d: Unexpected msg", line);
84 	zassert_equal(msg->log.hdr.timestamp, exp_timestamp, "%d: got:%d, exp:%d",
85 			line, (int)msg->log.hdr.timestamp, exp_timestamp);
86 
87 	z_log_msg_free(msg);
88 }
89 
90 #define CHECK_MSG(t) check_msg(t, __LINE__)
91 
ZTEST(log_link_order,test_log_only_local)92 ZTEST(log_link_order, test_log_only_local)
93 {
94 	struct log_msg log2;
95 	struct log_msg *log1;
96 
97 	log1 = z_log_msg_alloc(sizeof(struct log_msg) / sizeof(int));
98 	log1->hdr.desc.type = Z_LOG_MSG_LOG;
99 	log1->hdr.desc.package_len = 0;
100 	log1->hdr.desc.data_len = 0;
101 
102 	/* Commit local message. */
103 	z_log_msg_commit(log1);
104 
105 	log2.hdr.desc.type = Z_LOG_MSG_LOG;
106 	log2.hdr.desc.package_len = 0;
107 	log2.hdr.desc.data_len = 0;
108 
109 	log2.hdr.timestamp = timestamp_get();
110 
111 	z_log_msg_enqueue(&mock_link1, &log2, sizeof(log2));
112 
113 	CHECK_MSG(0);
114 	CHECK_MSG(1);
115 	CHECK_MSG(-1);
116 }
117 
ZTEST(log_link_order,test_log_local_unordered)118 ZTEST(log_link_order, test_log_local_unordered)
119 {
120 	struct log_msg *log1;
121 	struct log_msg log2;
122 
123 	/* Get timestamp for second message before first. Simulate that it is
124 	 * taken by remote.
125 	 */
126 	log_timestamp_t t = timestamp_get();
127 
128 	log1 = z_log_msg_alloc(sizeof(struct log_msg) / sizeof(int));
129 
130 	log1->hdr.desc.package_len = 0;
131 	log1->hdr.desc.data_len = 0;
132 
133 	/* Commit local message. */
134 	z_log_msg_commit(log1);
135 
136 	/* Simulate receiving of remote message. It is enqueued later but with
137 	 * earlier timestamp.
138 	 */
139 	log2.hdr.desc.type = Z_LOG_MSG_LOG;
140 	log2.hdr.timestamp = t;
141 	log2.hdr.desc.package_len = 0;
142 	log2.hdr.desc.data_len = 0;
143 
144 	z_log_msg_enqueue(&mock_link1, &log2, sizeof(log2));
145 
146 	CHECK_MSG(1);
147 	CHECK_MSG(0);
148 	CHECK_MSG(-1);
149 }
150 
ZTEST(log_link_order,test_log_one_remote_ordering)151 ZTEST(log_link_order, test_log_one_remote_ordering)
152 {
153 	struct log_msg *log1;
154 	struct log_msg log2;
155 
156 	/* Get timestamp for second message before first. Simulate that it is
157 	 * taken by remote.
158 	 */
159 	log_timestamp_t t = timestamp_get();
160 
161 	log1 = z_log_msg_alloc(sizeof(struct log_msg) / sizeof(int));
162 
163 	log1->hdr.desc.package_len = 0;
164 	log1->hdr.desc.data_len = 0;
165 
166 	/* Commit local message. */
167 	z_log_msg_commit(log1);
168 
169 	/* Simulate receiving of remote message. It is enqueued later but with
170 	 * earlier timestamp. However, it is enqueued to link with dedicated buffer
171 	 * thus when processing, earliest from the buffers is taken
172 	 */
173 
174 	log2.hdr.timestamp = t;
175 	log2.hdr.desc.type = Z_LOG_MSG_LOG;
176 	log2.hdr.desc.package_len = 0;
177 	log2.hdr.desc.data_len = 0;
178 
179 	/* link2 has dedicated buffer. */
180 	z_log_msg_enqueue(&mock_link2, &log2, sizeof(log2));
181 
182 	log2.hdr.timestamp = timestamp_get();
183 	/* link2 has dedicated buffer. Log another message with the latest timestamp. */
184 	z_log_msg_enqueue(&mock_link2, &log2, sizeof(log2));
185 
186 	CHECK_MSG(0);
187 	CHECK_MSG(1);
188 	CHECK_MSG(2);
189 	CHECK_MSG(-1);
190 }
191 
before(void * data)192 static void before(void *data)
193 {
194 	ARG_UNUSED(data);
195 
196 	log_setup();
197 }
198 
199 ZTEST_SUITE(log_link_order, NULL, NULL, before, NULL, NULL);
200