1 /*
2  * Copyright (c) 2024 Endress+Hauser AG
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <errno.h>
7 #include <zephyr/fff.h>
8 #include <zephyr/ztest.h>
9 #include "dns_cache.h"
10 
11 #define TEST_DNS_CACHE_SIZE        12
12 #define TEST_DNS_CACHE_DEFAULT_TTL 1
13 DNS_CACHE_DEFINE(test_dns_cache, TEST_DNS_CACHE_SIZE);
14 
clear_cache(void * fixture)15 void clear_cache(void *fixture)
16 {
17 	ARG_UNUSED(fixture);
18 	dns_cache_flush(&test_dns_cache);
19 }
20 
21 ZTEST_SUITE(net_dns_cache_test, NULL, NULL, clear_cache, NULL, NULL);
22 
ZTEST(net_dns_cache_test,test_simple_cache_entry)23 ZTEST(net_dns_cache_test, test_simple_cache_entry)
24 {
25 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
26 	struct dns_addrinfo info_read = {0};
27 	const char *query = "example.com";
28 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
29 
30 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write, TEST_DNS_CACHE_DEFAULT_TTL),
31 		   "Cache entry adding should work.");
32 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type, &info_read, 1));
33 	zassert_equal(AF_INET, info_read.ai_family);
34 }
35 
ZTEST(net_dns_cache_test,test_not_cached)36 ZTEST(net_dns_cache_test, test_not_cached)
37 {
38 	struct dns_addrinfo info_read = {0};
39 	const char *query = "example.com";
40 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
41 
42 	zassert_equal(0, dns_cache_find(&test_dns_cache, query, query_type, &info_read, 1));
43 	zassert_equal(0, info_read.ai_family);
44 }
45 
ZTEST(net_dns_cache_test,test_fill_cache)46 ZTEST(net_dns_cache_test, test_fill_cache)
47 {
48 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
49 	struct dns_addrinfo info_read[TEST_DNS_CACHE_SIZE] = {0};
50 	const char *query = "example.com";
51 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
52 
53 	for (size_t i = 0; i < TEST_DNS_CACHE_SIZE; i++) {
54 		zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write,
55 					 TEST_DNS_CACHE_DEFAULT_TTL),
56 			   "Cache entry adding should work.");
57 	}
58 	zassert_equal(TEST_DNS_CACHE_SIZE, dns_cache_find(&test_dns_cache, query, query_type,
59 							  info_read, TEST_DNS_CACHE_SIZE));
60 	zassert_equal(AF_INET, info_read[TEST_DNS_CACHE_SIZE - 1].ai_family);
61 }
62 
ZTEST(net_dns_cache_test,test_flush)63 ZTEST(net_dns_cache_test, test_flush)
64 {
65 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
66 	struct dns_addrinfo info_read[TEST_DNS_CACHE_SIZE] = {0};
67 	const char *query = "example.com";
68 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
69 
70 	for (size_t i = 0; i < TEST_DNS_CACHE_SIZE; i++) {
71 		zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write,
72 					 TEST_DNS_CACHE_DEFAULT_TTL),
73 			   "Cache entry adding should work.");
74 	}
75 	zassert_ok(dns_cache_flush(&test_dns_cache));
76 	zassert_equal(0, dns_cache_find(&test_dns_cache, query, query_type, info_read,
77 					TEST_DNS_CACHE_SIZE));
78 	zassert_equal(0, info_read[TEST_DNS_CACHE_SIZE - 1].ai_family);
79 }
80 
ZTEST(net_dns_cache_test,test_fill_cache_to_small)81 ZTEST(net_dns_cache_test, test_fill_cache_to_small)
82 {
83 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
84 	struct dns_addrinfo info_read[TEST_DNS_CACHE_SIZE - 1] = {0};
85 	const char *query = "example.com";
86 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
87 
88 	for (size_t i = 0; i < TEST_DNS_CACHE_SIZE; i++) {
89 		zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write,
90 					 TEST_DNS_CACHE_DEFAULT_TTL),
91 			   "Cache entry adding should work.");
92 	}
93 	zassert_equal(-ENOSR, dns_cache_find(&test_dns_cache, query, query_type, info_read,
94 					     TEST_DNS_CACHE_SIZE - 1));
95 	zassert_equal(AF_INET, info_read[TEST_DNS_CACHE_SIZE - 2].ai_family);
96 }
97 
ZTEST(net_dns_cache_test,test_closest_expiry_removed)98 ZTEST(net_dns_cache_test, test_closest_expiry_removed)
99 {
100 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
101 	struct dns_addrinfo info_read = {0};
102 	const char *closest_expiry = "example.com";
103 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
104 
105 	zassert_ok(dns_cache_add(&test_dns_cache, closest_expiry, &info_write,
106 				 TEST_DNS_CACHE_DEFAULT_TTL),
107 		   "Cache entry adding should work.");
108 	k_sleep(K_MSEC(1));
109 	for (size_t i = 0; i < TEST_DNS_CACHE_SIZE; i++) {
110 		zassert_ok(dns_cache_add(&test_dns_cache, "example2.com", &info_write,
111 					 TEST_DNS_CACHE_DEFAULT_TTL),
112 			   "Cache entry adding should work.");
113 	}
114 	zassert_equal(0,
115 		      dns_cache_find(&test_dns_cache, closest_expiry, query_type, &info_read, 1));
116 	zassert_equal(0, info_read.ai_family);
117 }
118 
ZTEST(net_dns_cache_test,test_expired_entries_removed)119 ZTEST(net_dns_cache_test, test_expired_entries_removed)
120 {
121 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
122 	struct dns_addrinfo info_read[3] = {0};
123 	const char *query = "example.com";
124 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
125 
126 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write, TEST_DNS_CACHE_DEFAULT_TTL),
127 		   "Cache entry adding should work.");
128 	zassert_ok(
129 		dns_cache_add(&test_dns_cache, query, &info_write, TEST_DNS_CACHE_DEFAULT_TTL * 2),
130 		"Cache entry adding should work.");
131 	zassert_ok(
132 		dns_cache_add(&test_dns_cache, query, &info_write, TEST_DNS_CACHE_DEFAULT_TTL * 3),
133 		"Cache entry adding should work.");
134 	zassert_equal(3, dns_cache_find(&test_dns_cache, query, query_type, info_read, 3));
135 	zassert_equal(AF_INET, info_read[0].ai_family);
136 	k_sleep(K_MSEC(TEST_DNS_CACHE_DEFAULT_TTL * 1000 + 1));
137 	zassert_equal(2, dns_cache_find(&test_dns_cache, query, query_type, info_read, 3));
138 	zassert_equal(AF_INET, info_read[0].ai_family);
139 	k_sleep(K_MSEC(TEST_DNS_CACHE_DEFAULT_TTL * 1000 + 1));
140 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type, info_read, 3));
141 	zassert_equal(AF_INET, info_read[0].ai_family);
142 	k_sleep(K_MSEC(1));
143 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type, info_read, 3));
144 	zassert_equal(AF_INET, info_read[0].ai_family);
145 }
146 
ZTEST(net_dns_cache_test,test_different_type_not_returned)147 ZTEST(net_dns_cache_test, test_different_type_not_returned)
148 {
149 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
150 	struct dns_addrinfo info_read = {0};
151 	const char *query = "example.com";
152 	enum dns_query_type query_type = DNS_QUERY_TYPE_AAAA;
153 
154 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write, TEST_DNS_CACHE_DEFAULT_TTL),
155 		   "Cache entry adding should work.");
156 	zassert_equal(0, dns_cache_find(&test_dns_cache, query, query_type, &info_read, 1));
157 	zassert_equal(0, info_read.ai_family);
158 }
159 
ZTEST(net_dns_cache_test,test_only_expected_type_returned)160 ZTEST(net_dns_cache_test, test_only_expected_type_returned)
161 {
162 	struct dns_addrinfo info_write_a = {.ai_family = AF_INET};
163 	struct dns_addrinfo info_write_b = {.ai_family = AF_INET6};
164 	struct dns_addrinfo info_read = {0};
165 	const char *query = "example.com";
166 	enum dns_query_type query_type_a = DNS_QUERY_TYPE_A;
167 	enum dns_query_type query_type_b = DNS_QUERY_TYPE_AAAA;
168 
169 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write_a, TEST_DNS_CACHE_DEFAULT_TTL),
170 		   "Cache entry adding should work.");
171 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write_b, TEST_DNS_CACHE_DEFAULT_TTL),
172 		   "Cache entry adding should work.");
173 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type_a, &info_read, 1));
174 	zassert_equal(AF_INET, info_read.ai_family);
175 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type_b, &info_read, 1));
176 	zassert_equal(AF_INET6, info_read.ai_family);
177 }
178 
ZTEST(net_dns_cache_test,test_remove_single_entry)179 ZTEST(net_dns_cache_test, test_remove_single_entry)
180 {
181 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
182 	struct dns_addrinfo info_read = {0};
183 	const char *query = "example.com";
184 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
185 
186 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write, TEST_DNS_CACHE_DEFAULT_TTL),
187 		   "Cache entry adding should work.");
188 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type, &info_read, 1));
189 	zassert_equal(AF_INET, info_read.ai_family);
190 
191 	zassert_ok(dns_cache_remove(&test_dns_cache, query), "Cache entry removal should work.");
192 	zassert_equal(0, dns_cache_find(&test_dns_cache, query, query_type, &info_read, 1));
193 }
194 
ZTEST(net_dns_cache_test,test_remove_multiple_entries_same_query)195 ZTEST(net_dns_cache_test, test_remove_multiple_entries_same_query)
196 {
197 	struct dns_addrinfo info_write_a = {.ai_family = AF_INET};
198 	struct dns_addrinfo info_write_b = {.ai_family = AF_INET6};
199 	struct dns_addrinfo info_read[2] = {0};
200 	const char *query = "example.com";
201 	enum dns_query_type query_type_a = DNS_QUERY_TYPE_A;
202 	enum dns_query_type query_type_b = DNS_QUERY_TYPE_AAAA;
203 
204 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write_a, TEST_DNS_CACHE_DEFAULT_TTL),
205 		   "Cache entry adding should work.");
206 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write_b, TEST_DNS_CACHE_DEFAULT_TTL),
207 		   "Cache entry adding should work.");
208 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type_a, &info_read[0], 1));
209 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type_b, &info_read[0], 1));
210 
211 	zassert_ok(dns_cache_remove(&test_dns_cache, query), "Cache entry removal should work.");
212 	zassert_equal(0, dns_cache_find(&test_dns_cache, query, query_type_a, &info_read[0], 1));
213 	zassert_equal(0, dns_cache_find(&test_dns_cache, query, query_type_b, &info_read[0], 1));
214 }
215 
ZTEST(net_dns_cache_test,test_remove_specific_query_only)216 ZTEST(net_dns_cache_test, test_remove_specific_query_only)
217 {
218 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
219 	struct dns_addrinfo info_read = {0};
220 	const char *query1 = "example.com";
221 	const char *query2 = "test.com";
222 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
223 
224 	zassert_ok(dns_cache_add(&test_dns_cache, query1, &info_write, TEST_DNS_CACHE_DEFAULT_TTL),
225 		   "Cache entry adding should work.");
226 	zassert_ok(dns_cache_add(&test_dns_cache, query2, &info_write, TEST_DNS_CACHE_DEFAULT_TTL),
227 		   "Cache entry adding should work.");
228 	zassert_equal(1, dns_cache_find(&test_dns_cache, query1, query_type, &info_read, 1));
229 	zassert_equal(1, dns_cache_find(&test_dns_cache, query2, query_type, &info_read, 1));
230 
231 	zassert_ok(dns_cache_remove(&test_dns_cache, query1), "Cache entry removal should work.");
232 	zassert_equal(0, dns_cache_find(&test_dns_cache, query1, query_type, &info_read, 1));
233 	zassert_equal(1, dns_cache_find(&test_dns_cache, query2, query_type, &info_read, 1));
234 	zassert_equal(AF_INET, info_read.ai_family);
235 }
236 
ZTEST(net_dns_cache_test,test_remove_nonexistent_query)237 ZTEST(net_dns_cache_test, test_remove_nonexistent_query)
238 {
239 	struct dns_addrinfo info_write = {.ai_family = AF_INET};
240 	struct dns_addrinfo info_read = {0};
241 	const char *query = "example.com";
242 	const char *nonexistent_query = "nonexistent.com";
243 	enum dns_query_type query_type = DNS_QUERY_TYPE_A;
244 
245 	zassert_ok(dns_cache_add(&test_dns_cache, query, &info_write, TEST_DNS_CACHE_DEFAULT_TTL),
246 		   "Cache entry adding should work.");
247 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type, &info_read, 1));
248 
249 	zassert_ok(dns_cache_remove(&test_dns_cache, nonexistent_query),
250 		   "Removing nonexistent query should not fail.");
251 	zassert_equal(1, dns_cache_find(&test_dns_cache, query, query_type, &info_read, 1));
252 	zassert_equal(AF_INET, info_read.ai_family);
253 }
254 
ZTEST(net_dns_cache_test,test_remove_empty_cache)255 ZTEST(net_dns_cache_test, test_remove_empty_cache)
256 {
257 	const char *query = "example.com";
258 
259 	zassert_ok(dns_cache_remove(&test_dns_cache, query),
260 		   "Removing from empty cache should not fail.");
261 }
262 
ZTEST(net_dns_cache_test,test_remove_null_parameters)263 ZTEST(net_dns_cache_test, test_remove_null_parameters)
264 {
265 	zassert_equal(-EINVAL, dns_cache_remove(NULL, "example.com"),
266 		      "NULL cache should return error.");
267 	zassert_equal(-EINVAL, dns_cache_remove(&test_dns_cache, NULL),
268 		      "NULL query should return error.");
269 }
270