1 /*
2 * Copyright (c) 2023 Meta
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8
9 #include <zephyr/ztest.h>
10 #include <zephyr/net/http/service.h>
11
12 #define DETAIL(n) (void *)((0xde7a11 * 10) + (n))
13 #define RES(n) (void *)((0x2e5 * 10) + (n))
14
15 /*
16 * Two separate HTTP server instances (A and B), each with different static
17 * resources, listening on different ports. Static resources could be, for
18 * example, gzip compressed html, javascript, css, or image files which
19 * have fixed paths known at build time.
20 *
21 * REST endpoints could be considered as static resources, as long as
22 * the paths (and implementation-specific details) are known at compile time.
23 */
24 static const uint16_t service_A_port = 4242;
25 HTTP_SERVICE_DEFINE(service_A, "a.service.com", &service_A_port, 4, 2, DETAIL(0));
26 HTTP_RESOURCE_DEFINE(resource_0, service_A, "/", RES(0));
27 HTTP_RESOURCE_DEFINE(resource_1, service_A, "/index.html", RES(1));
28
29 /* ephemeral port of 0 */
30 static uint16_t service_B_port;
31 HTTP_SERVICE_DEFINE(service_B, "b.service.com", &service_B_port, 7, 3, DETAIL(1));
32 HTTP_RESOURCE_DEFINE(resource_2, service_B, "/foo.htm", RES(2));
33 HTTP_RESOURCE_DEFINE(resource_3, service_B, "/bar/baz.php", RES(3));
34
35 /*
36 * An "empty" HTTP service is one without static resources. For example, a
37 * service which loads resources from a filesystem that are determined at
38 * runtime.
39 */
40 static const uint16_t service_C_port = 5959;
41 HTTP_SERVICE_DEFINE_EMPTY(service_C, "192.168.1.1", &service_C_port, 5, 9, DETAIL(2));
42
ZTEST(http_service,test_HTTP_SERVICE_DEFINE)43 ZTEST(http_service, test_HTTP_SERVICE_DEFINE)
44 {
45 zassert_ok(strcmp(service_A.host, "a.service.com"));
46 zassert_equal(service_A.port, &service_A_port);
47 zassert_equal(*service_A.port, 4242);
48 zassert_equal(service_A.detail, DETAIL(0));
49 zassert_equal(service_A.concurrent, 4);
50 zassert_equal(service_A.backlog, 2);
51
52 zassert_ok(strcmp(service_B.host, "b.service.com"));
53 zassert_equal(service_B.port, &service_B_port);
54 zassert_equal(*service_B.port, 0);
55 zassert_equal(service_B.detail, DETAIL(1));
56 zassert_equal(service_B.concurrent, 7);
57 zassert_equal(service_B.backlog, 3);
58
59 zassert_ok(strcmp(service_C.host, "192.168.1.1"));
60 zassert_equal(service_C.port, &service_C_port);
61 zassert_equal(*service_C.port, 5959);
62 zassert_equal(service_C.detail, DETAIL(2));
63 zassert_equal(service_C.concurrent, 5);
64 zassert_equal(service_C.backlog, 9);
65 zassert_equal(service_C.res_begin, NULL);
66 zassert_equal(service_C.res_end, NULL);
67 }
68
ZTEST(http_service,test_HTTP_SERVICE_COUNT)69 ZTEST(http_service, test_HTTP_SERVICE_COUNT)
70 {
71 size_t n_svc;
72
73 n_svc = 4273;
74 HTTP_SERVICE_COUNT(&n_svc);
75 zassert_equal(n_svc, 3);
76 }
77
ZTEST(http_service,test_HTTP_SERVICE_RESOURCE_COUNT)78 ZTEST(http_service, test_HTTP_SERVICE_RESOURCE_COUNT)
79 {
80 zassert_equal(HTTP_SERVICE_RESOURCE_COUNT(&service_A), 2);
81 zassert_equal(HTTP_SERVICE_RESOURCE_COUNT(&service_B), 2);
82 zassert_equal(HTTP_SERVICE_RESOURCE_COUNT(&service_C), 0);
83 }
84
ZTEST(http_service,test_HTTP_SERVICE_FOREACH)85 ZTEST(http_service, test_HTTP_SERVICE_FOREACH)
86 {
87 size_t n_svc = 0;
88 size_t have_service_A = 0;
89 size_t have_service_B = 0;
90 size_t have_service_C = 0;
91
92 HTTP_SERVICE_FOREACH(svc) {
93 if (svc == &service_A) {
94 have_service_A = 1;
95 } else if (svc == &service_B) {
96 have_service_B = 1;
97 } else if (svc == &service_C) {
98 have_service_C = 1;
99 } else {
100 zassert_unreachable("svc (%p) not equal to &service_A (%p), &service_B "
101 "(%p), or &service_C (%p)",
102 svc, &service_A, &service_B, &service_C);
103 }
104
105 n_svc++;
106 }
107
108 zassert_equal(n_svc, 3);
109 zassert_equal(have_service_A + have_service_B + have_service_C, n_svc);
110 }
111
ZTEST(http_service,test_HTTP_RESOURCE_FOREACH)112 ZTEST(http_service, test_HTTP_RESOURCE_FOREACH)
113 {
114 size_t first_res, second_res, n_res;
115
116 n_res = 0;
117 first_res = 0;
118 second_res = 0;
119 HTTP_RESOURCE_FOREACH(service_A, res) {
120 if (res == &resource_0) {
121 first_res = 1;
122 } else if (res == &resource_1) {
123 second_res = 1;
124 } else {
125 zassert_unreachable(
126 "res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res,
127 &resource_0, &resource_1);
128 }
129
130 n_res++;
131 }
132
133 zassert_equal(n_res, 2);
134 zassert_equal(first_res + second_res, n_res);
135
136 n_res = 0;
137 first_res = 0;
138 second_res = 0;
139 HTTP_RESOURCE_FOREACH(service_B, res) {
140 if (res == &resource_2) {
141 first_res = 1;
142 } else if (res == &resource_3) {
143 second_res = 1;
144 } else {
145 zassert_unreachable(
146 "res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res,
147 &resource_2, &resource_3);
148 }
149
150 n_res++;
151 }
152
153 zassert_equal(n_res, 2);
154 zassert_equal(first_res + second_res, n_res);
155
156 n_res = 0;
157 HTTP_SERVICE_FOREACH_RESOURCE(&service_C, res) {
158 zassert_unreachable("service_C does not have any resources");
159 n_res++;
160 }
161
162 zassert_equal(n_res, 0);
163 }
164
ZTEST(http_service,test_HTTP_SERVICE_FOREACH_RESOURCE)165 ZTEST(http_service, test_HTTP_SERVICE_FOREACH_RESOURCE)
166 {
167 size_t first_res, second_res, n_res;
168
169 n_res = 0;
170 first_res = 0;
171 second_res = 0;
172 HTTP_SERVICE_FOREACH_RESOURCE(&service_A, res) {
173 if (res == &resource_0) {
174 first_res = 1;
175 } else if (res == &resource_1) {
176 second_res = 1;
177 } else {
178 zassert_unreachable(
179 "res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res,
180 &resource_0, &resource_1);
181 }
182
183 n_res++;
184 }
185
186 zassert_equal(n_res, 2);
187 zassert_equal(first_res + second_res, n_res);
188
189 n_res = 0;
190 first_res = 0;
191 second_res = 0;
192 HTTP_SERVICE_FOREACH_RESOURCE(&service_B, res) {
193 if (res == &resource_2) {
194 first_res = 1;
195 } else if (res == &resource_3) {
196 second_res = 1;
197 } else {
198 zassert_unreachable(
199 "res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res,
200 &resource_2, &resource_3);
201 }
202
203 n_res++;
204 }
205
206 zassert_equal(n_res, 2);
207 zassert_equal(first_res + second_res, n_res);
208
209 n_res = 0;
210 HTTP_SERVICE_FOREACH_RESOURCE(&service_C, res) {
211 zassert_unreachable("service_C does not have any resources");
212 n_res++;
213 }
214
215 zassert_equal(n_res, 0);
216 }
217
ZTEST(http_service,test_HTTP_RESOURCE_DEFINE)218 ZTEST(http_service, test_HTTP_RESOURCE_DEFINE)
219 {
220 HTTP_SERVICE_FOREACH_RESOURCE(&service_A, res) {
221 if (res == &resource_0) {
222 zassert_ok(strcmp(res->resource, "/"));
223 zassert_equal(res->detail, RES(0));
224 } else if (res == &resource_1) {
225 zassert_ok(strcmp(res->resource, "/index.html"));
226 zassert_equal(res->detail, RES(1));
227 } else {
228 zassert_unreachable(
229 "res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res,
230 &resource_0, &resource_1);
231 }
232 }
233
234 HTTP_SERVICE_FOREACH_RESOURCE(&service_B, res) {
235 if (res == &resource_2) {
236 zassert_ok(strcmp(res->resource, "/foo.htm"));
237 zassert_equal(res->detail, RES(2));
238 } else if (res == &resource_3) {
239 zassert_ok(strcmp(res->resource, "/bar/baz.php"));
240 zassert_equal(res->detail, RES(3));
241 } else {
242 zassert_unreachable(
243 "res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res,
244 &resource_2, &resource_3);
245 }
246 }
247 }
248
249 ZTEST_SUITE(http_service, NULL, NULL, NULL, NULL, NULL);
250