1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery */
9*e7be843bSPierre Pronchery
10*e7be843bSPierre Pronchery #include "internal/qlog.h"
11*e7be843bSPierre Pronchery #include "testutil.h"
12*e7be843bSPierre Pronchery
13*e7be843bSPierre Pronchery /*
14*e7be843bSPierre Pronchery * Unfortunately, this must be expressed as an array and not a string literal as
15*e7be843bSPierre Pronchery * ANSI C only guarantees support for up to 509 characters in a string literal.
16*e7be843bSPierre Pronchery */
17*e7be843bSPierre Pronchery static const char expected[] = {
18*e7be843bSPierre Pronchery 30, '{', '"', 'q', 'l', 'o', 'g', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n',
19*e7be843bSPierre Pronchery '"', ':', '"', '0', '.', '3', '"', ',', '"', 'q', 'l', 'o', 'g', '_', 'f',
20*e7be843bSPierre Pronchery 'o', 'r', 'm', 'a', 't', '"', ':', '"', 'J', 'S', 'O', 'N', '-', 'S', 'E',
21*e7be843bSPierre Pronchery 'Q', '"', ',', '"', 't', 'i', 't', 'l', 'e', '"', ':', '"', 't', 'e', 's',
22*e7be843bSPierre Pronchery 't', ' ', 't', 'i', 't', 'l', 'e', '"', ',', '"', 'd', 'e', 's', 'c', 'r',
23*e7be843bSPierre Pronchery 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 't', 'e', 's', 't', ' ', 'd',
24*e7be843bSPierre Pronchery 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ',', '"', 't', 'r',
25*e7be843bSPierre Pronchery 'a', 'c', 'e', '"', ':', '{', '"', 'c', 'o', 'm', 'm', 'o', 'n', '_', 'f',
26*e7be843bSPierre Pronchery 'i', 'e', 'l', 'd', 's', '"', ':', '{', '"', 't', 'i', 'm', 'e', '_', 'f',
27*e7be843bSPierre Pronchery 'o', 'r', 'm', 'a', 't', '"', ':', '"', 'd', 'e', 'l', 't', 'a', '"', ',',
28*e7be843bSPierre Pronchery '"', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '_', 't', 'y', 'p', 'e', '"',
29*e7be843bSPierre Pronchery ':', '[', '"', 'Q', 'U', 'I', 'C', '"', ']', ',', '"', 'g', 'r', 'o', 'u',
30*e7be843bSPierre Pronchery 'p', '_', 'i', 'd', '"', ':', '"', 't', 'e', 's', 't', ' ', 'g', 'r', 'o',
31*e7be843bSPierre Pronchery 'u', 'p', ' ', 'I', 'D', '"', ',', '"', 's', 'y', 's', 't', 'e', 'm', '_',
32*e7be843bSPierre Pronchery 'i', 'n', 'f', 'o', '"', ':', '{', '"', 'p', 'r', 'o', 'c', 'e', 's', 's',
33*e7be843bSPierre Pronchery '_', 'i', 'd', '"', ':', '1', '2', '3', '}', '}', ',', '"', 'v', 'a', 'n',
34*e7be843bSPierre Pronchery 't', 'a', 'g', 'e', '_', 'p', 'o', 'i', 'n', 't', '"', ':', '{', '"', 't',
35*e7be843bSPierre Pronchery 'y', 'p', 'e', '"', ':', '"', 'c', 'l', 'i', 'e', 'n', 't', '"', ',', '"',
36*e7be843bSPierre Pronchery 'n', 'a', 'm', 'e', '"', ':', '"', 'O', 'p', 'e', 'n', 'S', 'S', 'L', '/',
37*e7be843bSPierre Pronchery 'x', '.', 'y', '.', 'z', '"', '}', '}', '}', 10, 30, '{', '"', 'n', 'a',
38*e7be843bSPierre Pronchery 'm', 'e', '"', ':', '"', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', ':',
39*e7be843bSPierre Pronchery 'p', 'a', 'c', 'k', 'e', 't', '_', 's', 'e', 'n', 't', '"', ',', '"', 'd',
40*e7be843bSPierre Pronchery 'a', 't', 'a', '"', ':', '{', '"', 'f', 'i', 'e', 'l', 'd', '1', '"', ':',
41*e7be843bSPierre Pronchery '"', 'f', 'o', 'o', '"', ',', '"', 'f', 'i', 'e', 'l', 'd', '2', '"', ':',
42*e7be843bSPierre Pronchery '"', 'b', 'a', 'r', '"', ',', '"', 'f', 'i', 'e', 'l', 'd', '3', '"', ':',
43*e7be843bSPierre Pronchery '4', '2', ',', '"', 'f', 'i', 'e', 'l', 'd', '4', '"', ':', '"', '1', '1',
44*e7be843bSPierre Pronchery '5', '2', '9', '2', '1', '5', '0', '4', '6', '0', '6', '8', '4', '6', '9',
45*e7be843bSPierre Pronchery '7', '6', '"', ',', '"', 'f', 'i', 'e', 'l', 'd', '5', '"', ':', '"', '1',
46*e7be843bSPierre Pronchery '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', '5', '5',
47*e7be843bSPierre Pronchery '1', '6', '1', '5', '"', ',', '"', 'f', 'i', 'e', 'l', 'd', '6', '"', ':',
48*e7be843bSPierre Pronchery 'f', 'a', 'l', 's', 'e', ',', '"', 'f', 'i', 'e', 'l', 'd', '7', '"', ':',
49*e7be843bSPierre Pronchery 't', 'r', 'u', 'e', ',', '"', 'f', 'i', 'e', 'l', 'd', '8', '"', ':', '"',
50*e7be843bSPierre Pronchery '0', '1', 'a', 'f', '"', ',', '"', 'f', 'i', 'e', 'l', 'd', '9', '"', ':',
51*e7be843bSPierre Pronchery '"', '5', '5', '"', ',', '"', 's', 'u', 'b', 'g', 'r', 'o', 'u', 'p', '"',
52*e7be843bSPierre Pronchery ':', '{', '"', 'f', 'i', 'e', 'l', 'd', '1', '0', '"', ':', '"', 'b', 'a',
53*e7be843bSPierre Pronchery 'z', '"', '}', ',', '"', 'a', 'r', 'r', 'a', 'y', '"', ':', '[', '"', 'a',
54*e7be843bSPierre Pronchery '"', ',', '"', 'b', '"', ']', '}', ',', '"', 't', 'i', 'm', 'e', '"', ':',
55*e7be843bSPierre Pronchery '1', '7', '0', '6', '5', '3', '1', '1', '7', '0', '0', '0', '}', 10, 30,
56*e7be843bSPierre Pronchery '{', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 't', 'r', 'a', 'n', 's', 'p',
57*e7be843bSPierre Pronchery 'o', 'r', 't', ':', 'p', 'a', 'c', 'k', 'e', 't', '_', 's', 'e', 'n', 't',
58*e7be843bSPierre Pronchery '"', ',', '"', 'd', 'a', 't', 'a', '"', ':', '{', '"', 'f', 'i', 'e', 'l',
59*e7be843bSPierre Pronchery 'd', '1', '"', ':', '"', 'b', 'a', 'r', '"', '}', ',', '"', 't', 'i', 'm',
60*e7be843bSPierre Pronchery 'e', '"', ':', '1', '0', '0', '0', '}', 10
61*e7be843bSPierre Pronchery };
62*e7be843bSPierre Pronchery
63*e7be843bSPierre Pronchery static const unsigned char bin_buf[] = {
64*e7be843bSPierre Pronchery 0x01, 0xaf
65*e7be843bSPierre Pronchery };
66*e7be843bSPierre Pronchery
67*e7be843bSPierre Pronchery static OSSL_TIME last_time;
68*e7be843bSPierre Pronchery
now(void * arg)69*e7be843bSPierre Pronchery static OSSL_TIME now(void *arg)
70*e7be843bSPierre Pronchery {
71*e7be843bSPierre Pronchery OSSL_TIME t = last_time;
72*e7be843bSPierre Pronchery
73*e7be843bSPierre Pronchery last_time = ossl_time_add(t, ossl_ms2time(1000));
74*e7be843bSPierre Pronchery return t;
75*e7be843bSPierre Pronchery }
76*e7be843bSPierre Pronchery
test_qlog(void)77*e7be843bSPierre Pronchery static int test_qlog(void)
78*e7be843bSPierre Pronchery {
79*e7be843bSPierre Pronchery int testresult = 0;
80*e7be843bSPierre Pronchery QLOG_TRACE_INFO qti = {0};
81*e7be843bSPierre Pronchery QLOG *qlog;
82*e7be843bSPierre Pronchery BIO *bio;
83*e7be843bSPierre Pronchery char *buf = NULL;
84*e7be843bSPierre Pronchery size_t buf_len = 0;
85*e7be843bSPierre Pronchery
86*e7be843bSPierre Pronchery last_time = ossl_time_from_time_t(170653117);
87*e7be843bSPierre Pronchery
88*e7be843bSPierre Pronchery qti.odcid.id_len = 1;
89*e7be843bSPierre Pronchery qti.odcid.id[0] = 0x55;
90*e7be843bSPierre Pronchery qti.title = "test title";
91*e7be843bSPierre Pronchery qti.description = "test description";
92*e7be843bSPierre Pronchery qti.group_id = "test group ID";
93*e7be843bSPierre Pronchery qti.override_process_id = 123;
94*e7be843bSPierre Pronchery qti.now_cb = now;
95*e7be843bSPierre Pronchery qti.override_impl_name = "OpenSSL/x.y.z";
96*e7be843bSPierre Pronchery
97*e7be843bSPierre Pronchery if (!TEST_ptr(qlog = ossl_qlog_new(&qti)))
98*e7be843bSPierre Pronchery goto err;
99*e7be843bSPierre Pronchery
100*e7be843bSPierre Pronchery if (!TEST_true(ossl_qlog_set_event_type_enabled(qlog, QLOG_EVENT_TYPE_transport_packet_sent, 1)))
101*e7be843bSPierre Pronchery goto err;
102*e7be843bSPierre Pronchery
103*e7be843bSPierre Pronchery if (!TEST_ptr(bio = BIO_new(BIO_s_mem())))
104*e7be843bSPierre Pronchery goto err;
105*e7be843bSPierre Pronchery
106*e7be843bSPierre Pronchery if (!TEST_true(ossl_qlog_set_sink_bio(qlog, bio)))
107*e7be843bSPierre Pronchery goto err;
108*e7be843bSPierre Pronchery
109*e7be843bSPierre Pronchery QLOG_EVENT_BEGIN(qlog, transport, packet_sent)
110*e7be843bSPierre Pronchery QLOG_STR("field1", "foo");
111*e7be843bSPierre Pronchery QLOG_STR_LEN("field2", "bar", 3);
112*e7be843bSPierre Pronchery QLOG_I64("field3", 42);
113*e7be843bSPierre Pronchery QLOG_I64("field4", 1ULL << 60);
114*e7be843bSPierre Pronchery QLOG_U64("field5", UINT64_MAX);
115*e7be843bSPierre Pronchery QLOG_BOOL("field6", 0);
116*e7be843bSPierre Pronchery QLOG_BOOL("field7", 1);
117*e7be843bSPierre Pronchery QLOG_BIN("field8", bin_buf, sizeof(bin_buf));
118*e7be843bSPierre Pronchery QLOG_CID("field9", &qti.odcid);
119*e7be843bSPierre Pronchery QLOG_BEGIN("subgroup")
120*e7be843bSPierre Pronchery QLOG_STR("field10", "baz");
121*e7be843bSPierre Pronchery QLOG_END()
122*e7be843bSPierre Pronchery QLOG_BEGIN_ARRAY("array")
123*e7be843bSPierre Pronchery QLOG_STR(NULL, "a");
124*e7be843bSPierre Pronchery QLOG_STR(NULL, "b");
125*e7be843bSPierre Pronchery QLOG_END_ARRAY()
126*e7be843bSPierre Pronchery QLOG_EVENT_END()
127*e7be843bSPierre Pronchery
128*e7be843bSPierre Pronchery /* not enabled */
129*e7be843bSPierre Pronchery QLOG_EVENT_BEGIN(qlog, transport, packet_received)
130*e7be843bSPierre Pronchery QLOG_STR("field1", "foo");
131*e7be843bSPierre Pronchery QLOG_EVENT_END()
132*e7be843bSPierre Pronchery
133*e7be843bSPierre Pronchery /* test delta time calculation */
134*e7be843bSPierre Pronchery QLOG_EVENT_BEGIN(qlog, transport, packet_sent)
135*e7be843bSPierre Pronchery QLOG_STR("field1", "bar");
136*e7be843bSPierre Pronchery QLOG_EVENT_END()
137*e7be843bSPierre Pronchery
138*e7be843bSPierre Pronchery if (!TEST_true(ossl_qlog_flush(qlog)))
139*e7be843bSPierre Pronchery goto err;
140*e7be843bSPierre Pronchery
141*e7be843bSPierre Pronchery buf_len = BIO_get_mem_data(bio, &buf);
142*e7be843bSPierre Pronchery if (!TEST_size_t_gt(buf_len, 0))
143*e7be843bSPierre Pronchery goto err;
144*e7be843bSPierre Pronchery
145*e7be843bSPierre Pronchery if (!TEST_mem_eq(buf, buf_len, expected, sizeof(expected)))
146*e7be843bSPierre Pronchery goto err;
147*e7be843bSPierre Pronchery
148*e7be843bSPierre Pronchery testresult = 1;
149*e7be843bSPierre Pronchery err:
150*e7be843bSPierre Pronchery ossl_qlog_free(qlog);
151*e7be843bSPierre Pronchery return testresult;
152*e7be843bSPierre Pronchery }
153*e7be843bSPierre Pronchery
154*e7be843bSPierre Pronchery struct filter_spec {
155*e7be843bSPierre Pronchery const char *filter;
156*e7be843bSPierre Pronchery int expect_ok;
157*e7be843bSPierre Pronchery uint32_t expect_event_type;
158*e7be843bSPierre Pronchery int expect_event_enable;
159*e7be843bSPierre Pronchery };
160*e7be843bSPierre Pronchery
161*e7be843bSPierre Pronchery static const struct filter_spec filters[] = {
162*e7be843bSPierre Pronchery { "*", 1,
163*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 1 },
164*e7be843bSPierre Pronchery { "-*", 1,
165*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 0 },
166*e7be843bSPierre Pronchery { "+*", 1,
167*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 1 },
168*e7be843bSPierre Pronchery { "* *", 1,
169*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_received, 1 },
170*e7be843bSPierre Pronchery { "-* +*", 1,
171*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_received, 1 },
172*e7be843bSPierre Pronchery { "-* +* -*", 1,
173*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_received, 0 },
174*e7be843bSPierre Pronchery { " *", 1,
175*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 1 },
176*e7be843bSPierre Pronchery { " ", 1,
177*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 0 },
178*e7be843bSPierre Pronchery { "", 1,
179*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 0 },
180*e7be843bSPierre Pronchery { "transport:packet_sent", 1,
181*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 1 },
182*e7be843bSPierre Pronchery { "transport:packet_sent", 1,
183*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_received, 0 },
184*e7be843bSPierre Pronchery { "* -transport:packet_sent", 1,
185*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_received, 1 },
186*e7be843bSPierre Pronchery { "* -transport:packet_sent", 1,
187*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 0 },
188*e7be843bSPierre Pronchery { "unknown:event", 1,
189*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 0 },
190*e7be843bSPierre Pronchery { "unknown:event +transport:packet_sent", 1,
191*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 1 },
192*e7be843bSPierre Pronchery { "unknown:event transport:*", 1,
193*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 1 },
194*e7be843bSPierre Pronchery { "unknown:event +transport:* -transport:packet_sent", 1,
195*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_received, 1 },
196*e7be843bSPierre Pronchery { "unknown:event transport:* -transport:packet_sent", 1,
197*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_packet_sent, 0 },
198*e7be843bSPierre Pronchery { "* -transport:*", 1,
199*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_connectivity_connection_started, 1 },
200*e7be843bSPierre Pronchery { "* -transport:*", 1,
201*e7be843bSPierre Pronchery QLOG_EVENT_TYPE_transport_parameters_set, 0 },
202*e7be843bSPierre Pronchery { "&", 0 },
203*e7be843bSPierre Pronchery { "event_name_without_category", 0 },
204*e7be843bSPierre Pronchery { "event_name_with_@badchar:foo", 0 },
205*e7be843bSPierre Pronchery { "event_name_with_badchar:f@oo", 0 },
206*e7be843bSPierre Pronchery { "category:", 0 },
207*e7be843bSPierre Pronchery { ":name", 0 },
208*e7be843bSPierre Pronchery { ":", 0 },
209*e7be843bSPierre Pronchery { "**", 0 },
210*e7be843bSPierre Pronchery { "foo:bar*", 0 },
211*e7be843bSPierre Pronchery { "foo:*bar", 0 },
212*e7be843bSPierre Pronchery { "foo*:bar", 0 },
213*e7be843bSPierre Pronchery { "*foo:bar", 0 },
214*e7be843bSPierre Pronchery };
215*e7be843bSPierre Pronchery
test_qlog_filter(int idx)216*e7be843bSPierre Pronchery static int test_qlog_filter(int idx)
217*e7be843bSPierre Pronchery {
218*e7be843bSPierre Pronchery int testresult = 0;
219*e7be843bSPierre Pronchery QLOG_TRACE_INFO qti = {0};
220*e7be843bSPierre Pronchery QLOG *qlog;
221*e7be843bSPierre Pronchery
222*e7be843bSPierre Pronchery qti.odcid.id_len = 1;
223*e7be843bSPierre Pronchery qti.odcid.id[0] = 0x55;
224*e7be843bSPierre Pronchery
225*e7be843bSPierre Pronchery if (!TEST_ptr(qlog = ossl_qlog_new(&qti)))
226*e7be843bSPierre Pronchery goto err;
227*e7be843bSPierre Pronchery
228*e7be843bSPierre Pronchery if (!TEST_int_eq(ossl_qlog_set_filter(qlog, filters[idx].filter),
229*e7be843bSPierre Pronchery filters[idx].expect_ok))
230*e7be843bSPierre Pronchery goto err;
231*e7be843bSPierre Pronchery
232*e7be843bSPierre Pronchery if (filters[idx].expect_event_type != QLOG_EVENT_TYPE_NONE)
233*e7be843bSPierre Pronchery if (!TEST_int_eq(ossl_qlog_enabled(qlog, filters[idx].expect_event_type),
234*e7be843bSPierre Pronchery filters[idx].expect_event_enable))
235*e7be843bSPierre Pronchery goto err;
236*e7be843bSPierre Pronchery
237*e7be843bSPierre Pronchery testresult = 1;
238*e7be843bSPierre Pronchery err:
239*e7be843bSPierre Pronchery ossl_qlog_free(qlog);
240*e7be843bSPierre Pronchery return testresult;
241*e7be843bSPierre Pronchery }
242*e7be843bSPierre Pronchery
setup_tests(void)243*e7be843bSPierre Pronchery int setup_tests(void)
244*e7be843bSPierre Pronchery {
245*e7be843bSPierre Pronchery ADD_TEST(test_qlog);
246*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_qlog_filter, OSSL_NELEM(filters));
247*e7be843bSPierre Pronchery return 1;
248*e7be843bSPierre Pronchery }
249