No issues found
1 #include <check.h>
2 #include <gtk/gtk.h>
3 #include <string.h>
4
5 #include "rb-debug.h"
6 #include "rb-file-helpers.h"
7 #include "rb-util.h"
8
9 #include "rhythmdb.h"
10 #include "rhythmdb-tree.h"
11
12 #include "rb-query-creator.h"
13
14 #include "test-utils.h"
15
16 #ifndef fail_if
17 #define fail_if(expr, ...) fail_unless(!(expr), "Failure '"#expr"' occured")
18 #endif
19
20 static gboolean
21 rb_value_array_equal (GArray *a1, GArray *a2)
22 {
23 int i;
24
25 if (a1 == NULL && a2 == NULL)
26 return TRUE;
27 else if (a1 == NULL || a2 == NULL)
28 return FALSE;
29
30 if (a1->len != a2->len)
31 return FALSE;
32
33 for (i = 0; i < a1->len; i++) {
34 GValue *v1, *v2;
35
36 v1 = &g_array_index (a1, GValue, i);
37 v2 = &g_array_index (a2, GValue, i);
38 if (rb_gvalue_compare (v1, v2) != 0)
39 return FALSE;
40 }
41
42 return TRUE;
43 }
44
45 static char *
46 rb_gvalue_array_to_string (GArray *a)
47 {
48 int i;
49 GString *s;
50
51 if (a == NULL)
52 return strdup ("");
53
54 s = g_string_new ("(");
55
56 for (i = 0; i < a->len; i++) {
57 GValue *val;
58
59 if (i != 0)
60 g_string_append (s, ", ");
61
62 val = &g_array_index (a, GValue, i);
63 switch (G_VALUE_TYPE (val)) {
64 case G_TYPE_STRING:
65 g_string_append_printf (s, "\"%s\"", g_value_get_string (val));
66 break;
67 case G_TYPE_BOOLEAN:
68 g_string_append_printf (s, "%d", g_value_get_boolean (val));
69 break;
70 case G_TYPE_INT:
71 g_string_append_printf (s, "%d", g_value_get_int (val));
72 break;
73 case G_TYPE_LONG:
74 g_string_append_printf (s, "%ld", g_value_get_long (val));
75 break;
76 case G_TYPE_ULONG:
77 g_string_append_printf (s, "%lu", g_value_get_ulong (val));
78 break;
79 case G_TYPE_UINT64:
80 g_string_append_printf (s, "%" G_GUINT64_FORMAT, g_value_get_uint64 (val));
81 break;
82 case G_TYPE_FLOAT:
83 g_string_append_printf (s, "%f", g_value_get_float (val));
84 break;
85 case G_TYPE_DOUBLE:
86 g_string_append_printf (s, "%f", g_value_get_double (val));
87 break;
88 case G_TYPE_POINTER:
89 g_string_append_printf (s, "P:%p", g_value_get_pointer (val));
90 break;
91 case G_TYPE_BOXED:
92 g_string_append_printf (s, "B:%p", g_value_get_boxed (val));
93 break;
94 case G_TYPE_OBJECT:
95 g_string_append_printf (s, "O:%p", g_value_get_object (val));
96 break;
97 default:
98 g_string_append(s, "Unknown");
99 }
100 }
101
102 g_string_append_c (s, ')');
103
104 return g_string_free (s, FALSE);
105 }
106
107 static gboolean
108 rhythmdb_query_equal (const RhythmDBQuery *q1, const RhythmDBQuery *q2)
109 {
110 int i;
111
112 if (q1 == NULL && q2 == NULL)
113 return TRUE;
114 else if (q1 == NULL || q2 == NULL)
115 return FALSE;
116
117 if (q1->len != q2->len)
118 return FALSE;
119
120 for (i = 0; i < q1->len; i++) {
121 RhythmDBQueryData *data1;
122 RhythmDBQueryData *data2;
123
124 data1 = g_ptr_array_index (q1, i);
125 data2 = g_ptr_array_index (q2, i);
126
127 if (data1->type != data2->type)
128 return FALSE;
129 if (data1->propid != data2->propid)
130 return FALSE;
131 if ((data1->val == NULL && data2->val != NULL) ||
132 (data1->val != NULL && data2->val == NULL))
133 return FALSE;
134 if ((data1->val != NULL && data2->val != NULL) &&
135 (rb_gvalue_compare (data1->val, data2->val) != 0))
136 return FALSE;
137 if (!rhythmdb_query_equal (data1->subquery, data2->subquery))
138 return FALSE;
139 }
140
141 return TRUE;
142 }
143
144
145 static void
146 query_creator_test_load_query (RhythmDB *db,
147 RhythmDBQuery *query,
148 RhythmDBQueryModelLimitType limit_type,
149 GArray *limit_value,
150 const char *sort_column,
151 gint sort_direction)
152 {
153 GtkWidget *creator;
154 RhythmDBQuery *squery;
155 RhythmDBQuery *query2 = NULL;
156 GArray *limit_value2 = NULL;
157 const char *sort_column2 = NULL;
158 RhythmDBQueryModelLimitType limit_type2;
159 gint sort_direction2;
160 char *str1, *str2;
161
162 squery = rhythmdb_query_parse (db,
163 RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, RHYTHMDB_ENTRY_TYPE_SONG,
164 RHYTHMDB_QUERY_SUBQUERY, query,
165 RHYTHMDB_QUERY_END);
166
167 creator = rb_query_creator_new_from_query (db,
168 squery,
169 limit_type, limit_value,
170 sort_column, sort_direction);
171
172 str1 = rhythmdb_query_to_string (db, squery);
173 fail_unless (creator != NULL,
174 "could not create query editor for %s", str1);
175
176 /* check queries */
177 query2 = rb_query_creator_get_query (RB_QUERY_CREATOR (creator));
178 str2 = rhythmdb_query_to_string (db, query2);
179 fail_unless (rhythmdb_query_equal (squery, query2),
180 "queries differ: %s; %s", str1, str2);
181 rhythmdb_query_free (query2);
182 g_free (str2);
183 g_free (str1);
184
185 /* check limits */
186 rb_query_creator_get_limit (RB_QUERY_CREATOR (creator),
187 &limit_type2, &limit_value2);
188 str1 = rb_gvalue_array_to_string (limit_value);
189 str2 = rb_gvalue_array_to_string (limit_value2);
190 fail_unless (limit_type == limit_type2,
191 "limit types differ: %d; %d", limit_type, limit_type2);
192 fail_unless (rb_value_array_equal (limit_value, limit_value2),
193 "limit values differ: %s; %s", str1, str2);
194 g_free (str2);
195 g_free (str1);
196 if (limit_value2)
197 g_array_unref (limit_value2);
198
199 /* check sorting */
200 rb_query_creator_get_sort_order (RB_QUERY_CREATOR (creator),
201 &sort_column2, &sort_direction2);
202 fail_unless (strcmp (sort_column2, sort_column) == 0,
203 "sort columns differ: %s; %s", sort_column, sort_column2);
204 fail_unless (sort_direction2 == sort_direction,
205 "sort directions differ: %d; %d", sort_direction, sort_direction2);
206
207 rhythmdb_query_free (squery);
208 gtk_widget_destroy (creator);
209 }
210
211 START_TEST (test_query_creator_load_query_empty)
212 {
213 RhythmDBQuery *query;
214
215 query = rhythmdb_query_parse (db,
216 RHYTHMDB_QUERY_END);
217 query_creator_test_load_query (db,
218 query,
219 RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
220 "Title", GTK_SORT_ASCENDING);
221 rhythmdb_query_free (query);
222 }
223 END_TEST
224
225 START_TEST (test_query_creator_load_query_simple)
226 {
227 RhythmDBQuery *query;
228
229 query = rhythmdb_query_parse (db,
230 RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TITLE, "foo",
231 RHYTHMDB_QUERY_END);
232 query_creator_test_load_query (db,
233 query,
234 RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
235 "Title", GTK_SORT_ASCENDING);
236 rhythmdb_query_free (query);
237 }
238 END_TEST
239
240 START_TEST (test_query_creator_load_query_multiple)
241 {
242 RhythmDBQuery *query;
243
244 query = rhythmdb_query_parse (db,
245 RHYTHMDB_QUERY_PROP_LIKE, RHYTHMDB_PROP_ARTIST_FOLDED, "bar",
246 RHYTHMDB_QUERY_PROP_PREFIX, RHYTHMDB_PROP_ARTIST_FOLDED, "bar",
247 RHYTHMDB_QUERY_PROP_LESS, RHYTHMDB_PROP_DURATION, 47,
248 RHYTHMDB_QUERY_END);
249 query_creator_test_load_query (db,
250 query,
251 RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
252 "Title", GTK_SORT_ASCENDING);
253 rhythmdb_query_free (query);
254 }
255 END_TEST
256
257 START_TEST (test_query_creator_load_query_disjunction)
258 {
259 RhythmDBQuery *query;
260
261 query = rhythmdb_query_parse (db,
262 RHYTHMDB_QUERY_PROP_YEAR_EQUALS, RHYTHMDB_PROP_DATE, 729025/*1997*/,
263 RHYTHMDB_QUERY_DISJUNCTION,
264 RHYTHMDB_QUERY_PROP_CURRENT_TIME_WITHIN, RHYTHMDB_PROP_LAST_PLAYED, 500,
265 RHYTHMDB_QUERY_END);
266 query_creator_test_load_query (db,
267 query,
268 RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
269 "Title", GTK_SORT_ASCENDING);
270 rhythmdb_query_free (query);
271 }
272 END_TEST
273
274 START_TEST (test_query_creator_load_limit_count)
275 {
276 RhythmDBQuery *query;
277 GArray *array;
278
279 query = rhythmdb_query_parse (db,
280 RHYTHMDB_QUERY_END);
281 array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 0);
282 g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
283 rb_value_array_append_data (array, G_TYPE_ULONG, 47);
284 query_creator_test_load_query (db,
285 query,
286 RHYTHMDB_QUERY_MODEL_LIMIT_COUNT, array,
287 "Title", GTK_SORT_ASCENDING);
288 rhythmdb_query_free (query);
289 g_array_unref (array);
290 }
291 END_TEST
292
293 START_TEST (test_query_creator_load_limit_minutes)
294 {
295 RhythmDBQuery *query;
296 GArray *array;
297
298 query = rhythmdb_query_parse (db,
299 RHYTHMDB_QUERY_END);
300 array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 0);
301 g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
302 rb_value_array_append_data (array, G_TYPE_ULONG, 37 * 60);
303 query_creator_test_load_query (db,
304 query,
305 RHYTHMDB_QUERY_MODEL_LIMIT_TIME, array,
306 "Title", GTK_SORT_ASCENDING);
307 rhythmdb_query_free (query);
308 g_array_unref (array);
309 }
310 END_TEST
311
312 START_TEST (test_query_creator_load_limit_hours)
313 {
314 RhythmDBQuery *query;
315 GArray *array;
316
317 query = rhythmdb_query_parse (db,
318 RHYTHMDB_QUERY_END);
319 array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 0);
320 g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
321 rb_value_array_append_data (array, G_TYPE_ULONG, 41 * 60 * 60);
322 query_creator_test_load_query (db,
323 query,
324 RHYTHMDB_QUERY_MODEL_LIMIT_TIME, array,
325 "Title", GTK_SORT_ASCENDING);
326 rhythmdb_query_free (query);
327 g_array_unref (array);
328 }
329 END_TEST
330
331 START_TEST (test_query_creator_load_limit_days)
332 {
333 RhythmDBQuery *query;
334 GArray *array;
335
336 query = rhythmdb_query_parse (db,
337 RHYTHMDB_QUERY_END);
338 array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 0);
339 g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
340 rb_value_array_append_data (array, G_TYPE_ULONG, 13 * 60 * 60 * 24);
341 query_creator_test_load_query (db,
342 query,
343 RHYTHMDB_QUERY_MODEL_LIMIT_TIME, array,
344 "Title", GTK_SORT_ASCENDING);
345 rhythmdb_query_free (query);
346 g_array_unref (array);
347 }
348 END_TEST
349
350 START_TEST (test_query_creator_load_limit_mb)
351 {
352 RhythmDBQuery *query;
353 GArray *array;
354
355 query = rhythmdb_query_parse (db,
356 RHYTHMDB_QUERY_END);
357 array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 0);
358 g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
359 rb_value_array_append_data (array, G_TYPE_UINT64, (guint64)13);
360 query_creator_test_load_query (db,
361 query,
362 RHYTHMDB_QUERY_MODEL_LIMIT_SIZE, array,
363 "Title", GTK_SORT_ASCENDING);
364 rhythmdb_query_free (query);
365 g_array_unref (array);
366 }
367 END_TEST
368
369 START_TEST (test_query_creator_load_limit_gb)
370 {
371 RhythmDBQuery *query;
372 GArray *array;
373
374 query = rhythmdb_query_parse (db,
375 RHYTHMDB_QUERY_END);
376 array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 0);
377 g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
378 rb_value_array_append_data (array, G_TYPE_UINT64, (guint64)(14 * 1000));
379 query_creator_test_load_query (db,
380 query,
381 RHYTHMDB_QUERY_MODEL_LIMIT_SIZE, array,
382 "Title", GTK_SORT_ASCENDING);
383 rhythmdb_query_free (query);
384 g_array_unref (array);
385 }
386 END_TEST
387
388 START_TEST (test_query_creator_load_sort_artist_dec)
389 {
390 RhythmDBQuery *query;
391
392 query = rhythmdb_query_parse (db,
393 RHYTHMDB_QUERY_END);
394 query_creator_test_load_query (db,
395 query,
396 RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
397 "Artist", GTK_SORT_DESCENDING);
398 rhythmdb_query_free (query);
399 }
400 END_TEST
401
402 static Suite *
403 rb_query_creator_suite (void)
404 {
405 Suite *s = suite_create ("RBQueryCreator");
406 TCase *tc_qls = tcase_create ("query_load-save");
407
408 /* test loading and retrieving various queries,
409 * ensuring the result is identical to the original
410 */
411 suite_add_tcase (s, tc_qls);
412 tcase_add_checked_fixture (tc_qls, test_rhythmdb_setup, test_rhythmdb_shutdown);
413 tcase_add_test (tc_qls, test_query_creator_load_query_empty);
414 tcase_add_test (tc_qls, test_query_creator_load_query_simple);
415 tcase_add_test (tc_qls, test_query_creator_load_query_multiple);
416 tcase_add_test (tc_qls, test_query_creator_load_query_disjunction);
417 tcase_add_test (tc_qls, test_query_creator_load_limit_count);
418 tcase_add_test (tc_qls, test_query_creator_load_limit_minutes);
419 tcase_add_test (tc_qls, test_query_creator_load_limit_hours);
420 tcase_add_test (tc_qls, test_query_creator_load_limit_days);
421 tcase_add_test (tc_qls, test_query_creator_load_limit_mb);
422 tcase_add_test (tc_qls, test_query_creator_load_limit_gb);
423 tcase_add_test (tc_qls, test_query_creator_load_sort_artist_dec);
424
425 return s;
426 }
427
428 int
429 main (int argc, char **argv)
430 {
431 int ret;
432 SRunner *sr;
433 Suite *s;
434
435 g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
436
437 rb_threads_init ();
438 rb_debug_init (TRUE);
439 rb_refstring_system_init ();
440 rb_file_helpers_init (TRUE);
441
442 /* setup tests */
443 s = rb_query_creator_suite ();
444 sr = srunner_create (s);
445
446 init_setup (sr, argc, argv);
447 init_once (FALSE);
448
449 srunner_run_all (sr, CK_NORMAL);
450 ret = srunner_ntests_failed (sr);
451 srunner_free (sr);
452
453 rb_file_helpers_shutdown ();
454 rb_refstring_system_shutdown ();
455
456 return ret;
457 }