Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright © 2018 Endless Mobile, Inc.
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Lesser General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2.1 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : : *
19 : : * Authors:
20 : : * - Philip Withnall <withnall@endlessm.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include <glib.h>
26 : : #include <gio/gio.h>
27 : : #include <libmogwai-tariff/tariff-loader.h>
28 : : #include <locale.h>
29 : :
30 : :
31 : : /* Test that get_tariff() returns %NULL if nothing’s been loaded. */
32 : : static void
33 : 1 : test_tariff_loader_unloaded (void)
34 : : {
35 : 1 : g_autoptr(MwtTariffLoader) loader = NULL;
36 : 1 : loader = mwt_tariff_loader_new ();
37 : :
38 [ - + ]: 1 : g_assert_null (mwt_tariff_loader_get_tariff (loader));
39 : 1 : }
40 : :
41 : : /* Test the tariff loader handles erroneous files gracefully.
42 : : * Note: These bytes are in version 1 format. */
43 : : static void
44 : 1 : test_tariff_loader_errors_bytes (void)
45 : : {
46 : : const struct
47 : : {
48 : : const guint8 *data;
49 : : gsize length;
50 : : }
51 : 1 : vectors[] =
52 : : {
53 : : /* Empty file */
54 : : { (const guint8 *) "", 0 },
55 : : /* Incorrect magic */
56 : : { (const guint8 *) "\x4c\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
57 : : "\x00\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
58 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
59 : : "\x74\x71\x75\x74\x29\x29\x0e", 46 },
60 : : /* Incorrect magic (not nul terminated) */
61 : : { (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
62 : : "\x01\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
63 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
64 : : "\x74\x71\x75\x74\x29\x29\x0e", 46 },
65 : : /* Incorrect version number */
66 : : { (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
67 : : "\x00\xf1\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
68 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
69 : : "\x74\x71\x75\x74\x29\x29\x0e", 46 },
70 : : /* Outer variant not in normal form (final byte changed) */
71 : : { (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
72 : : "\x00\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
73 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
74 : : "\x74\x71\x75\x74\x29\x29\x00", 46 },
75 : : /* Inner variant type not valid */
76 : : { (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
77 : : "\x00\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
78 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
79 : : "\x74\x71\x75\xff\x29\x29\x0e", 46 },
80 : : /* Inner variant invalid (name not nul terminated) */
81 : : { (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
82 : : "\xff\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
83 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
84 : : "\x74\x71\x75\x74\x29\x29\x0e", 46 },
85 : : /* Outer variant not valid (truncated) */
86 : : { (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
87 : : "\x00\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
88 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
89 : : "\x74", 40 },
90 : : /* Inner variant type valid but not correct for V1 of the format */
91 : : { (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
92 : : "\x00\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
93 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
94 : : "\x78\x71\x75\x74\x29\x29\x0e", 46 },
95 : : /* FIXME: Test validation of the tariff and period properties. Maybe do
96 : : * that using a GVariant? */
97 : : };
98 : :
99 : 1 : g_autoptr(MwtTariffLoader) loader = NULL;
100 : 1 : loader = mwt_tariff_loader_new ();
101 : :
102 [ + + ]: 10 : for (gsize i = 0; i < G_N_ELEMENTS (vectors); i++)
103 : : {
104 : 9 : g_autoptr(GError) error = NULL;
105 : 18 : g_autoptr(GBytes) bytes = g_bytes_new_static (vectors[i].data, vectors[i].length);
106 : :
107 : 9 : gboolean retval = mwt_tariff_loader_load_from_bytes (loader, bytes, &error);
108 [ + - + - : 9 : g_assert_error (error, MWT_TARIFF_ERROR, MWT_TARIFF_ERROR_INVALID);
- + ]
109 [ - + ]: 9 : g_assert_false (retval);
110 [ - + ]: 9 : g_assert_null (mwt_tariff_loader_get_tariff (loader));
111 : : }
112 : 1 : }
113 : :
114 : : /* Test the tariff loader handles erroneous files gracefully, when loading them
115 : : * from a #GVariant. */
116 : : static void
117 : 1 : test_tariff_loader_errors_variant (void)
118 : : {
119 : 1 : const gchar *vectors[] =
120 : : {
121 : : /* Invalid inner variant */
122 : : "('Mogwai tariff', @q 2, <''>)",
123 : : /* Invalid version number */
124 : : "('Mogwai tariff', @q 0, <@(sa(ttssqut)) ('a', [(0, 1, 'UTC', 'UTC', 0, 0, 0)])>)",
125 : : /* Invalid magic */
126 : : "('not magic', @q 2, <@(sa(ttssqut)) ('a', [(0, 1, 'UTC', 'UTC', 0, 0, 0)])>)",
127 : : /* Invalid outer type */
128 : : "('hello there', @q 1)",
129 : : "'boo'",
130 : : };
131 : :
132 : 1 : g_autoptr(MwtTariffLoader) loader = NULL;
133 : 1 : loader = mwt_tariff_loader_new ();
134 : :
135 [ + + ]: 6 : for (gsize i = 0; i < G_N_ELEMENTS (vectors); i++)
136 : : {
137 : 5 : g_autoptr(GError) local_error = NULL;
138 : 10 : g_autoptr(GVariant) variant = g_variant_parse (NULL, vectors[i],
139 : : NULL, NULL, &local_error);
140 [ - + ]: 5 : g_assert_no_error (local_error);
141 : :
142 : 5 : gboolean retval = mwt_tariff_loader_load_from_variant (loader, variant, &local_error);
143 [ + - + - : 5 : g_assert_error (local_error, MWT_TARIFF_ERROR, MWT_TARIFF_ERROR_INVALID);
- + ]
144 [ - + ]: 5 : g_assert_false (retval);
145 [ - + ]: 5 : g_assert_null (mwt_tariff_loader_get_tariff (loader));
146 : : }
147 : 1 : }
148 : :
149 : : /* Test loading a simple tariff from bytes works.
150 : : * Note: These bytes are in version 1 format. */
151 : : static void
152 : 1 : test_tariff_loader_simple_bytes (void)
153 : : {
154 : 1 : const guint8 *data =
155 : : (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66\x00"
156 : : "\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66\x66\x00"
157 : : "\x00\x00\x00\x00\x00\x7a\x49\x5a\x00\x00\x00\x00\x80\x58"
158 : : "\x72\x5a\x00\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00"
159 : : "\x00\x94\x35\x77\x00\x00\x00\x00\x80\x11\x50\x5a\x00\x00"
160 : : "\x00\x00\x80\xb4\x52\x5a\x00\x00\x00\x00\x03\x00\x00\x00"
161 : : "\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x0c\x00"
162 : : "\x28\x73\x61\x28\x74\x74\x71\x75\x74\x29\x29\x0e";
163 : 1 : const gsize len = 110;
164 : :
165 : 2 : g_autoptr(GBytes) bytes = g_bytes_new_static (data, len);
166 : 2 : g_autoptr(MwtTariffLoader) loader = mwt_tariff_loader_new ();
167 : 1 : g_autoptr(GError) error = NULL;
168 : :
169 : 1 : gboolean retval = mwt_tariff_loader_load_from_bytes (loader, bytes, &error);
170 [ - + ]: 1 : g_assert_no_error (error);
171 [ - + ]: 1 : g_assert_true (retval);
172 : :
173 : 1 : MwtTariff *tariff = mwt_tariff_loader_get_tariff (loader);
174 [ - + ]: 1 : g_assert_true (MWT_IS_TARIFF (tariff));
175 : :
176 : : /* Check properties. */
177 [ - + ]: 1 : g_assert_cmpstr (mwt_tariff_get_name (tariff), ==, "test-tariff");
178 : :
179 : 1 : GPtrArray *periods = mwt_tariff_get_periods (tariff);
180 [ - + ]: 1 : g_assert_cmpuint (periods->len, ==, 2);
181 : :
182 : 2 : g_autoptr(GDateTime) period1_start_expected = g_date_time_new_utc (2018, 1, 1, 0, 0, 0);
183 : 2 : g_autoptr(GDateTime) period1_end_expected = g_date_time_new_utc (2018, 2, 1, 0, 0, 0);
184 : :
185 : 1 : MwtPeriod *period1 = g_ptr_array_index (periods, 0);
186 : 1 : GDateTime *period1_start = mwt_period_get_start (period1);
187 : 1 : GDateTime *period1_end = mwt_period_get_end (period1);
188 [ - + ]: 1 : g_assert_true (g_date_time_equal (period1_start, period1_start_expected));
189 [ - + ]: 1 : g_assert_true (g_date_time_equal (period1_end, period1_end_expected));
190 [ - + ]: 1 : g_assert_cmpint (mwt_period_get_repeat_type (period1), ==, MWT_PERIOD_REPEAT_MONTH);
191 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_repeat_period (period1), ==, 1);
192 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_capacity_limit (period1), ==, 2 * 1000 * 1000 * 1000);
193 : :
194 : 2 : g_autoptr(GDateTime) period2_start_expected = g_date_time_new_utc (2018, 1, 6, 0, 0, 0);
195 : 2 : g_autoptr(GDateTime) period2_end_expected = g_date_time_new_utc (2018, 1, 8, 0, 0, 0);
196 : :
197 : 1 : MwtPeriod *period2 = g_ptr_array_index (periods, 1);
198 : 1 : GDateTime *period2_start = mwt_period_get_start (period2);
199 : 1 : GDateTime *period2_end = mwt_period_get_end (period2);
200 [ - + ]: 1 : g_assert_true (g_date_time_equal (period2_start, period2_start_expected));
201 [ - + ]: 1 : g_assert_true (g_date_time_equal (period2_end, period2_end_expected));
202 [ - + ]: 1 : g_assert_cmpint (mwt_period_get_repeat_type (period2), ==, MWT_PERIOD_REPEAT_WEEK);
203 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_repeat_period (period2), ==, 1);
204 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_capacity_limit (period2), ==, G_MAXUINT64);
205 : 1 : }
206 : :
207 : : /* Test loading a simple tariff from a serialised #GVariant works. It’s not a
208 : : * very exciting tariff. */
209 : : static void
210 : 1 : test_tariff_loader_simple_variant (void)
211 : : {
212 : 1 : g_autoptr(GError) local_error = NULL;
213 : :
214 : 1 : const gchar *variant_str =
215 : : "('Mogwai tariff', @q 2, <@(sa(ttssqut)) ('a', [(0, 1, 'UTC', 'UTC', 0, 0, 0)])>)";
216 : 2 : g_autoptr(GVariant) variant = g_variant_parse (NULL, variant_str, NULL, NULL, &local_error);
217 [ - + ]: 1 : g_assert_no_error (local_error);
218 : :
219 : 2 : g_autoptr(MwtTariffLoader) loader = mwt_tariff_loader_new ();
220 : :
221 : 1 : gboolean retval = mwt_tariff_loader_load_from_variant (loader, variant, &local_error);
222 [ - + ]: 1 : g_assert_no_error (local_error);
223 [ - + ]: 1 : g_assert_true (retval);
224 : :
225 : 1 : MwtTariff *tariff = mwt_tariff_loader_get_tariff (loader);
226 [ - + ]: 1 : g_assert_true (MWT_IS_TARIFF (tariff));
227 : :
228 : : /* Check properties. */
229 [ - + ]: 1 : g_assert_cmpstr (mwt_tariff_get_name (tariff), ==, "a");
230 : :
231 : 1 : GPtrArray *periods = mwt_tariff_get_periods (tariff);
232 [ - + ]: 1 : g_assert_cmpuint (periods->len, ==, 1);
233 : :
234 : 2 : g_autoptr(GDateTime) period1_start_expected = g_date_time_new_utc (1970, 1, 1, 0, 0, 0);
235 : 2 : g_autoptr(GDateTime) period1_end_expected = g_date_time_new_utc (1970, 1, 1, 0, 0, 1);
236 : :
237 : 1 : MwtPeriod *period1 = g_ptr_array_index (periods, 0);
238 : 1 : GDateTime *period1_start = mwt_period_get_start (period1);
239 : 1 : GDateTime *period1_end = mwt_period_get_end (period1);
240 [ - + ]: 1 : g_assert_true (g_date_time_equal (period1_start, period1_start_expected));
241 [ - + ]: 1 : g_assert_true (g_date_time_equal (period1_end, period1_end_expected));
242 [ - + ]: 1 : g_assert_cmpint (mwt_period_get_repeat_type (period1), ==, MWT_PERIOD_REPEAT_NONE);
243 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_repeat_period (period1), ==, 0);
244 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_capacity_limit (period1), ==, 0);
245 : 1 : }
246 : :
247 : : /* Test that loading a tariff with no periods fails gracefully.
248 : : * Note: These bytes are in version 1 format. */
249 : : static void
250 : 1 : test_tariff_loader_empty (void)
251 : : {
252 : 1 : const guint8 *data =
253 : : (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
254 : : "\x00\x01\x00\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
255 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
256 : : "\x74\x71\x75\x74\x29\x29\x0e";
257 : 1 : const gsize len = 46;
258 : :
259 : 2 : g_autoptr(GBytes) bytes = g_bytes_new_static (data, len);
260 : 2 : g_autoptr(MwtTariffLoader) loader = mwt_tariff_loader_new ();
261 : 1 : g_autoptr(GError) error = NULL;
262 : :
263 : 1 : gboolean retval = mwt_tariff_loader_load_from_bytes (loader, bytes, &error);
264 [ + - + - : 1 : g_assert_error (error, MWT_TARIFF_ERROR, MWT_TARIFF_ERROR_INVALID);
- + ]
265 [ - + ]: 1 : g_assert_false (retval);
266 : :
267 : 1 : MwtTariff *tariff = mwt_tariff_loader_get_tariff (loader);
268 [ - + ]: 1 : g_assert_null (tariff);
269 : 1 : }
270 : :
271 : : /* Test that loading a byteswapped tariff with no periods also fails.
272 : : * Note: These bytes are in version 1 format. */
273 : : static void
274 : 1 : test_tariff_loader_empty_byteswapped (void)
275 : : {
276 : 1 : const guint8 *data =
277 : : (const guint8 *) "\x4d\x6f\x67\x77\x61\x69\x20\x74\x61\x72\x69\x66\x66"
278 : : "\x00\x00\x01\x74\x65\x73\x74\x2d\x74\x61\x72\x69\x66"
279 : : "\x66\x00\x00\x00\x00\x00\x0c\x00\x28\x73\x61\x28\x74"
280 : : "\x74\x71\x75\x74\x29\x29\x0e";
281 : 1 : const gsize len = 46;
282 : :
283 : 2 : g_autoptr(GBytes) bytes = g_bytes_new_static (data, len);
284 : 2 : g_autoptr(MwtTariffLoader) loader = mwt_tariff_loader_new ();
285 : 1 : g_autoptr(GError) error = NULL;
286 : :
287 : 1 : gboolean retval = mwt_tariff_loader_load_from_bytes (loader, bytes, &error);
288 [ + - + - : 1 : g_assert_error (error, MWT_TARIFF_ERROR, MWT_TARIFF_ERROR_INVALID);
- + ]
289 [ - + ]: 1 : g_assert_false (retval);
290 : :
291 : 1 : MwtTariff *tariff = mwt_tariff_loader_get_tariff (loader);
292 [ - + ]: 1 : g_assert_null (tariff);
293 : 1 : }
294 : :
295 : : int
296 : 1 : main (int argc,
297 : : char **argv)
298 : : {
299 : 1 : setlocale (LC_ALL, "");
300 : 1 : g_test_init (&argc, &argv, NULL);
301 : :
302 : 1 : g_test_add_func ("/tariff-loader/unloaded", test_tariff_loader_unloaded);
303 : 1 : g_test_add_func ("/tariff-loader/errors/bytes", test_tariff_loader_errors_bytes);
304 : 1 : g_test_add_func ("/tariff-loader/errors/variant", test_tariff_loader_errors_variant);
305 : 1 : g_test_add_func ("/tariff-loader/simple/bytes", test_tariff_loader_simple_bytes);
306 : 1 : g_test_add_func ("/tariff-loader/simple/variant", test_tariff_loader_simple_variant);
307 : 1 : g_test_add_func ("/tariff-loader/empty", test_tariff_loader_empty);
308 : 1 : g_test_add_func ("/tariff-loader/empty/byteswapped",
309 : : test_tariff_loader_empty_byteswapped);
310 : :
311 : 1 : return g_test_run ();
312 : : }
|