Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright 2025 GNOME Foundation, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General Public
18 : : * License along with this library; if not, write to the Free Software
19 : : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 : : *
21 : : * Authors:
22 : : * - Philip Withnall <pwithnall@gnome.org>
23 : : */
24 : :
25 : : #include "config.h"
26 : :
27 : : #include <glib.h>
28 : : #include <gio/gio.h>
29 : : #include <libmalcontent/manager.h>
30 : : #include <libmalcontent/web-filter.h>
31 : : #include <libglib-testing/dbus-queue.h>
32 : : #include <locale.h>
33 : : #include <string.h>
34 : : #include "accounts-service-iface.h"
35 : : #include "accounts-service-extension-iface.h"
36 : :
37 : :
38 : : /* Test that the #GType definitions for various types work. */
39 : : static void
40 : 1 : test_web_filter_types (void)
41 : : {
42 : 1 : g_type_ensure (mct_web_filter_get_type ());
43 : 1 : g_type_ensure (mct_web_filter_builder_get_type ());
44 : 1 : }
45 : :
46 : : /* Test that ref() and unref() work on an #MctWebFilter. */
47 : : static void
48 : 1 : test_web_filter_refs (void)
49 : : {
50 : 1 : g_auto(MctWebFilterBuilder) builder = MCT_WEB_FILTER_BUILDER_INIT ();
51 : 1 : g_autoptr(MctWebFilter) filter = NULL;
52 : :
53 : : /* Use an empty #MctWebFilter. */
54 : 1 : filter = mct_web_filter_builder_end (&builder);
55 : :
56 : 1 : g_assert_nonnull (filter);
57 : :
58 : : /* Call a method to check that the filter hasn’t been finalised. */
59 : 1 : g_assert_false (mct_web_filter_get_force_safe_search (filter));
60 : 1 : mct_web_filter_ref (filter);
61 : 1 : g_assert_false (mct_web_filter_get_force_safe_search (filter));
62 : 1 : mct_web_filter_unref (filter);
63 : 1 : g_assert_false (mct_web_filter_get_force_safe_search (filter));
64 : :
65 : : /* Final ref is dropped by g_autoptr(). */
66 : 1 : }
67 : :
68 : : /* Basic test of mct_web_filter_serialize() on a web filter. */
69 : : static void
70 : 1 : test_web_filter_serialize (void)
71 : : {
72 : 1 : g_auto(MctWebFilterBuilder) builder = MCT_WEB_FILTER_BUILDER_INIT ();
73 : 1 : g_autoptr(MctWebFilter) filter = NULL;
74 : 1 : g_autoptr(GVariant) serialized = NULL;
75 : :
76 : : /* Use an empty #MctWebFilter. */
77 : 1 : filter = mct_web_filter_builder_end (&builder);
78 : :
79 : : /* We can’t assert anything about the serialisation format, since it’s opaque. */
80 : 1 : serialized = mct_web_filter_serialize (filter);
81 : 1 : g_assert_nonnull (serialized);
82 : 1 : }
83 : :
84 : : /* Basic test of mct_web_filter_deserialize() on various current and historic
85 : : * serialised web filter variants. */
86 : : static void
87 : 1 : test_web_filter_deserialize (void)
88 : : {
89 : : /* These are all opaque. Older versions should be kept around to test
90 : : * backwards compatibility. */
91 : 1 : const gchar *valid_web_filters[] =
92 : : {
93 : : "@a{sv} {}",
94 : : "{ 'FilterType': <@u 0> }",
95 : : "{ 'FilterType': <@u 1>, 'BlockLists': <{'easylist': 'https://v.firebog.net/hosts/Easylist.txt'}> }",
96 : : "{ 'ForceSafeSearch': <true> }",
97 : : };
98 : :
99 [ + + ]: 5 : for (gsize i = 0; i < G_N_ELEMENTS (valid_web_filters); i++)
100 : : {
101 : 4 : g_autoptr(GVariant) serialized = NULL;
102 : 4 : g_autoptr(MctWebFilter) filter = NULL;
103 : 4 : g_autoptr(GError) local_error = NULL;
104 : :
105 : 4 : g_test_message ("%" G_GSIZE_FORMAT ": %s", i, valid_web_filters[i]);
106 : :
107 : 4 : serialized = g_variant_parse (NULL, valid_web_filters[i], NULL, NULL, NULL);
108 : 4 : g_assert (serialized != NULL);
109 : :
110 : 4 : filter = mct_web_filter_deserialize (serialized, 1, &local_error);
111 : 4 : g_assert_no_error (local_error);
112 : 4 : g_assert_nonnull (filter);
113 : : }
114 : 1 : }
115 : :
116 : : /* Test of mct_web_filter_deserialize() on various invalid variants. */
117 : : static void
118 : 1 : test_web_filter_deserialize_invalid (void)
119 : : {
120 : 1 : const gchar *invalid_web_filters[] =
121 : : {
122 : : "false",
123 : : "()",
124 : : "{ 'FilterType': <@u 600> }",
125 : : };
126 : :
127 [ + + ]: 4 : for (gsize i = 0; i < G_N_ELEMENTS (invalid_web_filters); i++)
128 : : {
129 : 3 : g_autoptr(GVariant) serialized = NULL;
130 : 3 : g_autoptr(MctWebFilter) filter = NULL;
131 : 3 : g_autoptr(GError) local_error = NULL;
132 : :
133 : 3 : g_test_message ("%" G_GSIZE_FORMAT ": %s", i, invalid_web_filters[i]);
134 : :
135 : 3 : serialized = g_variant_parse (NULL, invalid_web_filters[i], NULL, NULL, NULL);
136 : 3 : g_assert (serialized != NULL);
137 : :
138 : 3 : filter = mct_web_filter_deserialize (serialized, 1, &local_error);
139 : 3 : g_assert_error (local_error, MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_INVALID_DATA);
140 : 3 : g_assert_null (filter);
141 : : }
142 : 1 : }
143 : :
144 : : /* Test that mct_web_filter_equal() returns the correct results on various
145 : : * web filters. */
146 : : static void
147 : 1 : test_web_filter_equal (void)
148 : : {
149 : 1 : g_auto(MctWebFilterBuilder) builder = MCT_WEB_FILTER_BUILDER_INIT ();
150 : : MctWebFilter *equal_filters[2];
151 : 1 : const char *unequal_filters_serialised[] =
152 : : {
153 : : "@a{sv} {}",
154 : : "{ 'FilterType': <@u 1>, 'BlockLists': <{'easylist': 'https://v.firebog.net/hosts/Easylist.txt'}> }",
155 : : "{ 'FilterType': <@u 1>, 'BlockLists': <{'easylist': 'https://v.firebog.net/hosts/Easylist.txt', 'hardlist': 'https://v.firebog.net/hosts/Hardlist.txt'}> }",
156 : : "{ 'FilterType': <@u 1>, 'AllowLists': <{'easylist': 'https://v.firebog.net/hosts/Easylist.txt'}> }",
157 : : "{ 'ForceSafeSearch': <true> }",
158 : : };
159 : : MctWebFilter *unequal_filters[G_N_ELEMENTS (unequal_filters_serialised)];
160 : :
161 : : /* Build a couple of filters which are identical. */
162 : 1 : equal_filters[0] = mct_web_filter_builder_end (&builder);
163 : :
164 : 1 : mct_web_filter_builder_init (&builder);
165 : 1 : equal_filters[1] = mct_web_filter_builder_end (&builder);
166 : :
167 : : /* And a load of filters which are not. */
168 [ + + ]: 6 : for (size_t i = 0; i < G_N_ELEMENTS (unequal_filters_serialised); i++)
169 : : {
170 : 5 : g_autoptr(GVariant) serialized = NULL;
171 : :
172 : 5 : serialized = g_variant_parse (NULL, unequal_filters_serialised[i], NULL, NULL, NULL);
173 : 5 : g_assert (serialized != NULL);
174 : :
175 : 5 : unequal_filters[i] = mct_web_filter_deserialize (serialized, 1, NULL);
176 : 5 : g_assert (unequal_filters[i] != NULL);
177 : : }
178 : :
179 : : /* Test the equality checks on them all. */
180 [ + + ]: 3 : for (size_t i = 0; i < G_N_ELEMENTS (equal_filters); i++)
181 [ + + ]: 6 : for (size_t j = 0; j < G_N_ELEMENTS (equal_filters); j++)
182 : 4 : g_assert_true (mct_web_filter_equal (equal_filters[i], equal_filters[j]));
183 : :
184 [ + + ]: 6 : for (size_t i = 0; i < G_N_ELEMENTS (unequal_filters); i++)
185 : : {
186 [ + + ]: 15 : for (size_t j = 0; j < G_N_ELEMENTS (equal_filters); j++)
187 : 10 : g_assert_false (mct_web_filter_equal (unequal_filters[i], equal_filters[j]));
188 [ + + ]: 30 : for (size_t j = 0; j < G_N_ELEMENTS (unequal_filters); j++)
189 : : {
190 [ + + ]: 25 : if (i != j)
191 : 20 : g_assert_false (mct_web_filter_equal (unequal_filters[i], unequal_filters[j]));
192 : : else
193 : 5 : g_assert_true (mct_web_filter_equal (unequal_filters[i], unequal_filters[j]));
194 : : }
195 : : }
196 : :
197 [ + + ]: 3 : for (size_t i = 0; i < G_N_ELEMENTS (equal_filters); i++)
198 : 2 : mct_web_filter_unref (equal_filters[i]);
199 [ + + ]: 6 : for (size_t i = 0; i < G_N_ELEMENTS (unequal_filters); i++)
200 : 5 : mct_web_filter_unref (unequal_filters[i]);
201 : 1 : }
202 : :
203 : : static void
204 : 1 : test_web_filter_validate_filter_id (void)
205 : : {
206 : 1 : const char *valid_ids[] =
207 : : {
208 : : "a",
209 : : "hi",
210 : : };
211 : 1 : const char *invalid_ids[] =
212 : : {
213 : : "",
214 : : };
215 : :
216 [ + + ]: 3 : for (size_t i = 0; i < G_N_ELEMENTS (valid_ids); i++)
217 : 2 : g_assert_true (mct_web_filter_validate_filter_id (valid_ids[i]));
218 : :
219 [ + + ]: 2 : for (size_t i = 0; i < G_N_ELEMENTS (invalid_ids); i++)
220 : 1 : g_assert_false (mct_web_filter_validate_filter_id (invalid_ids[i]));
221 : 1 : }
222 : :
223 : : static void
224 : 1 : test_web_filter_validate_hostname (void)
225 : : {
226 : 1 : const char *valid_hostnames[] =
227 : : {
228 : : "a",
229 : : "reddit.com",
230 : : "www.rfc-editor.org",
231 : : };
232 : 1 : const char *invalid_hostnames[] =
233 : : {
234 : : "",
235 : : "123456781234567812345678123456781234567812345678123456781234567."
236 : : "123456781234567812345678123456781234567812345678123456781234567."
237 : : "123456781234567812345678123456781234567812345678123456781234567."
238 : : "12345678123456781234567812345678123456781234567812345678123456",
239 : : "1234567812345678123456781234567812345678123456781234567812345678.labeltoolong",
240 : : "@",
241 : : "@.invalidcharacter",
242 : : "-.hyphenonlylabel",
243 : : "-startswithhyphen",
244 : : "endswithhyphen-",
245 : : };
246 : :
247 [ + + ]: 4 : for (size_t i = 0; i < G_N_ELEMENTS (valid_hostnames); i++)
248 : 3 : g_assert_true (mct_web_filter_validate_hostname (valid_hostnames[i]));
249 : :
250 [ + + ]: 9 : for (size_t i = 0; i < G_N_ELEMENTS (invalid_hostnames); i++)
251 : 8 : g_assert_false (mct_web_filter_validate_hostname (invalid_hostnames[i]));
252 : 1 : }
253 : :
254 : : int
255 : 1 : main (int argc,
256 : : char **argv)
257 : : {
258 : 1 : setlocale (LC_ALL, "");
259 : 1 : g_test_init (&argc, &argv, NULL);
260 : :
261 : 1 : g_test_add_func ("/web-filter/types", test_web_filter_types);
262 : 1 : g_test_add_func ("/web-filter/refs", test_web_filter_refs);
263 : :
264 : 1 : g_test_add_func ("/web-filter/serialize", test_web_filter_serialize);
265 : 1 : g_test_add_func ("/web-filter/deserialize", test_web_filter_deserialize);
266 : 1 : g_test_add_func ("/web-filter/deserialize/invalid", test_web_filter_deserialize_invalid);
267 : :
268 : 1 : g_test_add_func ("/web-filter/equal", test_web_filter_equal);
269 : :
270 : 1 : g_test_add_func ("/web-filter/validate-filter-id", test_web_filter_validate_filter_id);
271 : 1 : g_test_add_func ("/web-filter/validate-hostname", test_web_filter_validate_hostname);
272 : :
273 : 1 : return g_test_run ();
274 : : }
|