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 
14 #include <zephyr/tc_util.h>
15 #include <stdbool.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/ztest.h>
18 #include <zephyr/logging/log_backend.h>
19 #include <zephyr/logging/log_ctrl.h>
20 #include <zephyr/logging/log.h>
21 #include "mock_log_link.h"
22 
23 LOG_MODULE_REGISTER(test);
24 
process(const struct log_backend * const backend,union log_msg_generic * msg)25 static void process(const struct log_backend *const backend,
26 			union log_msg_generic *msg)
27 {
28 
29 }
30 
panic(const struct log_backend * const backend)31 static void panic(const struct log_backend *const backend)
32 {
33 
34 }
35 
36 const struct log_backend_api log_backend_test_api = {
37 	.process = process,
38 	.panic = panic
39 };
40 
41 LOG_BACKEND_DEFINE(backend1, log_backend_test_api, false);
42 
43 LOG_BACKEND_DEFINE(backend2, log_backend_test_api, false);
44 
log_setup(bool backend2_enable)45 static void log_setup(bool backend2_enable)
46 {
47 	uint8_t offset = 0;
48 
49 	log_init();
50 	(void)z_log_links_activate(0xFFFFFFFF, &offset);
51 
52 	log_backend_enable(&backend1, NULL, LOG_LEVEL_DBG);
53 
54 	if (backend2_enable) {
55 		log_backend_enable(&backend2, NULL, LOG_LEVEL_INF);
56 	} else {
57 		log_backend_disable(&backend2);
58 	}
59 }
60 
61 
62 struct mock_log_link_source domain1_sources[] = {
63 	{ .source = "abc", .clevel = 4, .rlevel = 4},
64 	{ .source = "xxx", .clevel = 3, .rlevel = 3},
65 	{ .source = "yyy", .clevel = 2, .rlevel = 2},
66 	{ .source = "zzz", .clevel = 4, .rlevel = 1},
67 };
68 
69 struct mock_log_link_source domain2_sources[] = {
70 	{ .source = "abc2", .clevel = 2, .rlevel = 1},
71 	{ .source = "xxx2", .clevel = 2, .rlevel = 2},
72 	{ .source = "yyy2", .clevel = 3, .rlevel = 3},
73 	{ .source = "zzz2", .clevel = 4, .rlevel = 4},
74 };
75 
76 struct mock_log_link_source domain3_sources[] = {
77 	{ .source = "abc", .clevel = 4, .rlevel = 4},
78 	{ .source = "xxx", .clevel = 3, .rlevel = 3},
79 	{ .source = "yyy", .clevel = 2, .rlevel = 2},
80 	{ .source = "zzz", .clevel = 2, .rlevel = 1},
81 };
82 
83 struct mock_log_link_domain domain1 = {
84 	.source_cnt = ARRAY_SIZE(domain1_sources),
85 	.sources = domain1_sources,
86 	.name = "domain1"
87 };
88 
89 struct mock_log_link_domain domain2 = {
90 	.source_cnt = ARRAY_SIZE(domain2_sources),
91 	.sources = domain2_sources,
92 	.name = "domain2"
93 };
94 
95 struct mock_log_link_domain domain3 = {
96 	.source_cnt = ARRAY_SIZE(domain3_sources),
97 	.sources = domain3_sources,
98 	.name = "domain3"
99 };
100 
101 struct mock_log_link_domain *domains_a[] = {&domain1, &domain2};
102 struct mock_log_link mock_link_a = {
103 	.domain_cnt = ARRAY_SIZE(domains_a),
104 	.domains = domains_a
105 };
106 
107 struct mock_log_link_domain *domains_b[] = {&domain3};
108 struct mock_log_link mock_link_b = {
109 	.domain_cnt = ARRAY_SIZE(domains_b),
110 	.domains = domains_b
111 };
112 
113 extern struct log_link_api mock_log_link_api;
114 
115 LOG_LINK_DEF(mock_link1, mock_log_link_api, 0, &mock_link_a);
116 LOG_LINK_DEF(mock_link2, mock_log_link_api, 0, &mock_link_b);
117 
ZTEST(log_links,test_log_domain_count)118 ZTEST(log_links, test_log_domain_count)
119 {
120 	uint8_t domains_cnt;
121 	uint8_t exp_domains_cnt;
122 
123 	log_setup(false);
124 
125 	exp_domains_cnt = 1 + mock_link_a.domain_cnt + mock_link_b.domain_cnt;
126 	domains_cnt = log_domains_count();
127 	zassert_equal(domains_cnt, exp_domains_cnt,
128 			"Unexpected number of domains (%d)", domains_cnt);
129 }
130 
ZTEST(log_links,test_log_source_count)131 ZTEST(log_links, test_log_source_count)
132 {
133 	uint8_t exp_source_cnt[] = {
134 		log_const_source_id(TYPE_SECTION_END(log_const)),
135 		/*link1*/
136 		domains_a[0]->source_cnt,
137 		domains_a[1]->source_cnt,
138 		domains_b[0]->source_cnt,
139 	};
140 
141 	log_setup(false);
142 
143 
144 	for (uint8_t d = 0; d < log_domains_count(); d++) {
145 		uint16_t source_cnt = log_src_cnt_get(d);
146 
147 		zassert_equal(source_cnt, exp_source_cnt[d],
148 			      "Unexpected source count (%d:%d)", d, source_cnt);
149 	}
150 }
151 
test_single_compile_level(uint8_t d,uint16_t s,uint32_t exp_level)152 static void test_single_compile_level(uint8_t d, uint16_t s, uint32_t exp_level)
153 {
154 	uint32_t level = log_filter_get(NULL, d, s, false);
155 
156 	zassert_equal(level, exp_level,
157 			"%d:%d Unexpected compiled level (%d vs %d)",
158 			d, s, level, exp_level);
159 }
160 
ZTEST(log_links,test_log_compiled_level_get)161 ZTEST(log_links, test_log_compiled_level_get)
162 {
163 	log_setup(false);
164 
165 	test_single_compile_level(1, 0, domains_a[0]->sources[0].clevel);
166 	test_single_compile_level(1, 1, domains_a[0]->sources[1].clevel);
167 	test_single_compile_level(1, 3, domains_a[0]->sources[3].clevel);
168 	test_single_compile_level(2, 2, domains_a[1]->sources[2].clevel);
169 	test_single_compile_level(3, 2, domains_b[0]->sources[2].clevel);
170 }
171 
test_single_runtime_level(uint8_t d,uint16_t s,uint8_t * link_level)172 static void test_single_runtime_level(uint8_t d, uint16_t s, uint8_t *link_level)
173 {
174 	uint32_t level1;
175 	uint32_t level2;
176 
177 	level1 = log_filter_get(&backend1, d, s, true);
178 	level2 = log_filter_get(&backend2, d, s, true);
179 	zassert_equal(level1, *link_level,
180 			"%d:%d Unexpected compiled level (%d vs %d)",
181 			d, s, level1, *link_level);
182 	zassert_equal(level2, MIN(*link_level, LOG_LEVEL_INF),
183 			"%d:%d Unexpected compiled level (%d vs %d)",
184 			d, s, level2, MIN(*link_level, LOG_LEVEL_INF));
185 
186 	log_filter_set(&backend1, d, s, 1);
187 	log_filter_set(&backend2, d, s, 2);
188 	level1 = log_filter_get(&backend1, d, s, true);
189 	level2 = log_filter_get(&backend2, d, s, true);
190 	zassert_equal(level1, 1, "%d:%d Unexpected compiled level (%d vs %d)",
191 			d, s, level1, 1);
192 	zassert_equal(level2, 2, "%d:%d Unexpected compiled level (%d vs %d)",
193 			d, s, level2, 2);
194 
195 	/* level set in link should be the max of both level set */
196 	zassert_equal(*link_level, 2,
197 			"%d:%d Unexpected compiled level (got:%d exp:%d)",
198 			d, s, *link_level, 2);
199 
200 }
201 
ZTEST(log_links,test_log_runtime_level_set)202 ZTEST(log_links, test_log_runtime_level_set)
203 {
204 	log_setup(true);
205 
206 	test_single_runtime_level(1, 0, &domains_a[0]->sources[0].rlevel);
207 	test_single_runtime_level(1, 3, &domains_a[0]->sources[3].rlevel);
208 	test_single_runtime_level(2, 1, &domains_a[1]->sources[1].rlevel);
209 	test_single_runtime_level(3, 1, &domains_b[0]->sources[1].rlevel);
210 }
211 
ZTEST(log_links,test_log_domain_name_get)212 ZTEST(log_links, test_log_domain_name_get)
213 {
214 	zassert_equal(strcmp(log_domain_name_get(0), ""), 0,
215 			"Unexpected domain name");
216 	zassert_equal(strcmp(log_domain_name_get(1), "domain1"), 0,
217 			"Unexpected domain name (%s)", log_domain_name_get(1));
218 	zassert_equal(strcmp(log_domain_name_get(2), "domain2"), 0,
219 			"Unexpected domain name (%s)", log_domain_name_get(2));
220 	zassert_equal(strcmp(log_domain_name_get(3), "domain3"), 0,
221 			"Unexpected domain name (%s)", log_domain_name_get(3));
222 }
223 
test_single_log_source_name_get(uint8_t d,uint16_t s,const char * exp_name)224 static void test_single_log_source_name_get(uint8_t d, uint16_t s,
225 						const char *exp_name)
226 {
227 	const char *name = log_source_name_get(d, s);
228 
229 	zassert_equal(strcmp(name, exp_name), 0, "%d:%d Unexpected source name",
230 			d, s);
231 }
232 
ZTEST(log_links,test_log_source_name_get)233 ZTEST(log_links, test_log_source_name_get)
234 {
235 	log_setup(false);
236 
237 	test_single_log_source_name_get(1, 0, domains_a[0]->sources[0].source);
238 	test_single_log_source_name_get(1, 1, domains_a[0]->sources[1].source);
239 	test_single_log_source_name_get(2, 2, domains_a[1]->sources[2].source);
240 	test_single_log_source_name_get(3, 3, domains_b[0]->sources[3].source);
241 }
242 
243 ZTEST_SUITE(log_links, NULL, NULL, NULL, NULL, NULL);
244