1 #include <gom/gom.h>
2 #include <glib/gstdio.h>
3 
4 static GMainLoop *gMainLoop;
5 
6 /* EpisodeResource object */
7 
8 #define EPISODE_TYPE_RESOURCE              (episode_resource_get_type())
9 #define EPISODE_TYPE_TYPE                  (episode_type_get_type())
10 #define EPISODE_RESOURCE(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPISODE_TYPE_RESOURCE, EpisodeResource))
11 #define EPISODE_RESOURCE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), EPISODE_TYPE_RESOURCE, EpisodeResourceClass))
12 #define EPISODE_IS_RESOURCE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPISODE_TYPE_RESOURCE))
13 #define EPISODE_IS_RESOURCE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), EPISODE_TYPE_RESOURCE))
14 #define EPISODE_RESOURCE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), EPISODE_TYPE_RESOURCE, EpisodeResourceClass))
15 
16 #define EPISODE_COLUMN_ID                 "id"
17 #define EPISODE_COLUMN_SERIES_ID          "series-id"
18 #define EPISODE_COLUMN_IMDB_ID            "imdb-id"
19 #define EPISODE_COLUMN_SEASON_NUMBER      "season-number"
20 #define EPISODE_COLUMN_EPISODE_NUMBER     "episode-number"
21 #define EPISODE_COLUMN_EPISODE_NAME       "episode-name"
22 
23 typedef struct {
24   gint64      db_id;
25   gchar      *series_id;
26   gchar      *imdb_id;
27   guint8      season_number;
28   guint8      episode_number;
29   gchar      *episode_name;
30 } EpisodeResourcePrivate;
31 
32 typedef struct
33 {
34    GomResource parent;
35    EpisodeResourcePrivate *priv;
36 } EpisodeResource;
37 
38 typedef struct
39 {
40    GomResourceClass parent_class;
41 } EpisodeResourceClass;
42 
43 GType episode_resource_get_type(void);
44 
45 G_DEFINE_TYPE(EpisodeResource, episode_resource, GOM_TYPE_RESOURCE)
46 
47 enum {
48   PROP_0,
49   PROP_DB_ID,
50   PROP_SERIES_ID,
51   PROP_IMDB_ID,
52   PROP_SEASON_NUMBER,
53   PROP_EPISODE_NUMBER,
54   PROP_EPISODE_NAME,
55   LAST_PROP
56 };
57 
58 static GParamSpec *specs[LAST_PROP];
59 
60 static struct {
61   const gchar *series_id;
62   const gchar *imdb_id;
63   guint8       season_number;
64   guint8       episode_number;
65   const gchar *episode_name;
66 } values[] = {
67   { "84947", "tt2483070", 4, 1, "New York Sour" },
68   { "84947", "tt2778300", 4, 2, "Resignation" },
69   { "84947", "tt3767076", 5, 2, "The Good Listener" },
70   { "84947", "tt3767078", 5, 3, NULL }
71 };
72 
73 static void
episode_resource_finalize(GObject * object)74 episode_resource_finalize (GObject *object)
75 {
76   EpisodeResourcePrivate *priv = EPISODE_RESOURCE(object)->priv;
77 
78   g_clear_pointer (&priv->series_id, g_free);
79   g_clear_pointer (&priv->imdb_id, g_free);
80   g_clear_pointer (&priv->episode_name, g_free);
81 
82   G_OBJECT_CLASS(episode_resource_parent_class)->finalize(object);
83 }
84 
85 static void
episode_resource_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)86 episode_resource_get_property (GObject    *object,
87                                guint       prop_id,
88                                GValue     *value,
89                                GParamSpec *pspec)
90 {
91   EpisodeResource *resource = EPISODE_RESOURCE(object);
92 
93   switch (prop_id) {
94   case PROP_DB_ID:
95     g_value_set_int64 (value, resource->priv->db_id);
96     break;
97   case PROP_SERIES_ID:
98     g_value_set_string (value, resource->priv->series_id);
99     break;
100   case PROP_IMDB_ID:
101     g_value_set_string (value, resource->priv->imdb_id);
102     break;
103   case PROP_SEASON_NUMBER:
104     g_value_set_uchar (value, resource->priv->season_number);
105     break;
106   case PROP_EPISODE_NUMBER:
107     g_value_set_uchar (value, resource->priv->episode_number);
108     break;
109   case PROP_EPISODE_NAME:
110     g_value_set_string (value, resource->priv->episode_name);
111     break;
112   default:
113     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
114   }
115 }
116 
117 static void
episode_resource_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)118 episode_resource_set_property (GObject      *object,
119                                guint         prop_id,
120                                const GValue *value,
121                                GParamSpec   *pspec)
122 {
123   EpisodeResource *resource = EPISODE_RESOURCE(object);
124 
125   switch (prop_id) {
126   case PROP_DB_ID:
127     resource->priv->db_id = g_value_get_int64 (value);
128     break;
129   case PROP_SERIES_ID:
130     g_clear_pointer (&resource->priv->series_id, g_free);
131     resource->priv->series_id = g_value_dup_string (value);
132     break;
133   case PROP_IMDB_ID:
134     g_clear_pointer (&resource->priv->imdb_id, g_free);
135     resource->priv->imdb_id = g_value_dup_string (value);
136     break;
137   case PROP_SEASON_NUMBER:
138     resource->priv->season_number = g_value_get_uchar (value);
139     break;
140   case PROP_EPISODE_NUMBER:
141     resource->priv->episode_number = g_value_get_uchar (value);
142     break;
143   case PROP_EPISODE_NAME:
144     g_clear_pointer (&resource->priv->episode_name, g_free);
145     resource->priv->episode_name = g_value_dup_string (value);
146     break;
147   default:
148     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
149   }
150 }
151 
152 static void
episode_resource_class_init(EpisodeResourceClass * klass)153 episode_resource_class_init (EpisodeResourceClass *klass)
154 {
155   GObjectClass *object_class;
156   GomResourceClass *resource_class;
157 
158   object_class = G_OBJECT_CLASS(klass);
159   object_class->finalize = episode_resource_finalize;
160   object_class->get_property = episode_resource_get_property;
161   object_class->set_property = episode_resource_set_property;
162   g_type_class_add_private(object_class, sizeof(EpisodeResourcePrivate));
163 
164   resource_class = GOM_RESOURCE_CLASS(klass);
165   gom_resource_class_set_table(resource_class, "episodes");
166 
167   specs[PROP_DB_ID] = g_param_spec_int64 (EPISODE_COLUMN_ID,
168                                           NULL, NULL,
169                                           0, G_MAXINT64,
170                                           0, G_PARAM_READWRITE);
171   g_object_class_install_property (object_class, PROP_DB_ID,
172                                    specs[PROP_DB_ID]);
173   gom_resource_class_set_primary_key (resource_class, "id");
174 
175   specs[PROP_SERIES_ID] = g_param_spec_string (EPISODE_COLUMN_SERIES_ID,
176                                                NULL, NULL, NULL,
177                                                G_PARAM_READWRITE);
178   g_object_class_install_property (object_class, PROP_SERIES_ID,
179                                    specs[PROP_SERIES_ID]);
180 
181   specs[PROP_IMDB_ID] = g_param_spec_string (EPISODE_COLUMN_IMDB_ID,
182                                              NULL, NULL, NULL,
183                                              G_PARAM_READWRITE);
184   g_object_class_install_property (object_class, PROP_IMDB_ID,
185                                    specs[PROP_IMDB_ID]);
186 
187   specs[PROP_SEASON_NUMBER] = g_param_spec_uchar (EPISODE_COLUMN_SEASON_NUMBER,
188                                                   NULL, NULL,
189                                                   0, G_MAXUINT8,
190                                                   0, G_PARAM_READWRITE);
191   g_object_class_install_property (object_class, PROP_SEASON_NUMBER,
192                                    specs[PROP_SEASON_NUMBER]);
193 
194   specs[PROP_EPISODE_NUMBER] = g_param_spec_uchar (EPISODE_COLUMN_EPISODE_NUMBER,
195                                                    NULL, NULL,
196                                                    0, G_MAXUINT8,
197                                                    0, G_PARAM_READWRITE);
198   g_object_class_install_property (object_class, PROP_EPISODE_NUMBER,
199                                    specs[PROP_EPISODE_NUMBER]);
200 
201   specs[PROP_EPISODE_NAME] = g_param_spec_string (EPISODE_COLUMN_EPISODE_NAME,
202                                                   NULL, NULL, NULL,
203                                                   G_PARAM_READWRITE);
204   g_object_class_install_property (object_class, PROP_EPISODE_NAME,
205                                    specs[PROP_EPISODE_NAME]);
206 
207 }
208 
209 static void
episode_resource_init(EpisodeResource * resource)210 episode_resource_init (EpisodeResource *resource)
211 {
212   resource->priv = G_TYPE_INSTANCE_GET_PRIVATE(resource,
213                                                EPISODE_TYPE_RESOURCE,
214                                                EpisodeResourcePrivate);
215 }
216 
217 static void
create_memory_db(GomAdapter ** adapter,GomRepository ** repository)218 create_memory_db (GomAdapter **adapter,
219                   GomRepository **repository)
220 {
221   gboolean ret;
222   GError *error = NULL;
223   GList *object_types;
224   EpisodeResource *eres;
225   guint i;
226 
227   *adapter = gom_adapter_new();
228   ret = gom_adapter_open_sync (*adapter, ":memory:", &error);
229   //ret = gom_adapter_open_sync (*adapter, "/tmp/test_gom_find.db", &error);
230   g_assert_no_error (error);
231   g_assert (ret);
232 
233   *repository = gom_repository_new (*adapter);
234 
235   object_types = g_list_prepend (NULL, GINT_TO_POINTER (EPISODE_TYPE_RESOURCE));
236   ret = gom_repository_automatic_migrate_sync (*repository, 1, object_types, &error);
237   g_assert_no_error (error);
238   g_assert (ret);
239 
240   for (i = 0; i < G_N_ELEMENTS(values); i++) {
241     eres = g_object_new (EPISODE_TYPE_RESOURCE,
242                          "repository", *repository,
243                          EPISODE_COLUMN_SERIES_ID, values[i].series_id,
244                          EPISODE_COLUMN_IMDB_ID, values[i].imdb_id,
245                          EPISODE_COLUMN_SEASON_NUMBER, values[i].season_number,
246                          EPISODE_COLUMN_EPISODE_NUMBER, values[i].episode_number,
247                          EPISODE_COLUMN_EPISODE_NAME, values[i].episode_name,
248                          NULL);
249     ret = gom_resource_save_sync (GOM_RESOURCE (eres), &error);
250     g_assert (ret);
251     g_assert_no_error (error);
252     g_object_unref (eres);
253   }
254 }
255 
256 static void
free_memory_db(GomAdapter * adapter,GomRepository * repository)257 free_memory_db (GomAdapter *adapter,
258                 GomRepository *repository)
259 {
260   gboolean ret;
261   GError *error = NULL;
262 
263   ret = gom_adapter_close_sync (adapter, &error);
264   g_assert_no_error (error);
265   g_assert (ret);
266 
267   g_object_unref (repository);
268   g_object_unref (adapter);
269 }
270 
271 /* Try to find values[0] from values[0].series_id */
272 static void
find_simple(void)273 find_simple (void)
274 {
275   GError *error = NULL;
276   GValue value = { 0, };
277   GomFilter *filter;
278   char *s1, *s2;
279   GomResource *resource;
280   EpisodeResource *eres;
281   GomAdapter *adapter;
282   GomRepository *repository;
283 
284   create_memory_db (&adapter, &repository);
285 
286   /* Series ID */
287   g_value_init (&value, G_TYPE_STRING);
288   g_value_set_string (&value, values[0].series_id);
289   filter = gom_filter_new_like (EPISODE_TYPE_RESOURCE,
290                                 EPISODE_COLUMN_SERIES_ID,
291                                 &value);
292   g_value_unset (&value);
293 
294   resource = gom_repository_find_one_sync (repository,
295                                            EPISODE_TYPE_RESOURCE,
296                                            filter,
297                                            &error);
298   g_assert_no_error (error);
299   g_assert (resource);
300   g_object_unref (filter);
301   eres = EPISODE_RESOURCE (resource);
302 
303   g_object_get(eres,
304                EPISODE_COLUMN_SERIES_ID, &s1,
305                EPISODE_COLUMN_IMDB_ID, &s2,
306                NULL);
307   g_object_unref(eres);
308 
309   g_assert_cmpstr (s1, ==, values[0].series_id);
310   g_assert_cmpstr (s2, ==, values[0].imdb_id);
311   g_free (s1);
312   g_free (s2);
313 
314   free_memory_db (adapter, repository);
315 }
316 
317 /* Try to find values[0] from:
318  * values[0].series_id
319  * AND values[0].season_number
320  * AND values[0].episode_number */
321 static void
find_specific(void)322 find_specific (void)
323 {
324   GError *error = NULL;
325   GValue value = { 0, };
326   GomFilter *filter1, *filter2, *filter3, *filter4, *filter5;
327   char *s1, *s2;
328   GomResource *resource;
329   EpisodeResource *eres;
330   GomAdapter *adapter;
331   GomRepository *repository;
332 
333   create_memory_db (&adapter, &repository);
334 
335   /* Season Number */
336   g_value_init (&value, G_TYPE_INT64);
337   g_value_set_int64 (&value, values[0].season_number);
338   filter1 = gom_filter_new_eq (EPISODE_TYPE_RESOURCE,
339                                EPISODE_COLUMN_SEASON_NUMBER,
340                                &value);
341   g_value_unset (&value);
342 
343   /* Episode Number */
344   g_value_init (&value, G_TYPE_INT64);
345   g_value_set_int64 (&value, values[0].episode_number);
346   filter2 = gom_filter_new_eq (EPISODE_TYPE_RESOURCE,
347                                EPISODE_COLUMN_EPISODE_NUMBER,
348                                &value);
349   g_value_unset (&value);
350 
351   /* Series ID */
352   g_value_init (&value, G_TYPE_STRING);
353   g_value_set_string (&value, values[0].series_id);
354   filter3 = gom_filter_new_like (EPISODE_TYPE_RESOURCE,
355                                  EPISODE_COLUMN_SERIES_ID,
356                                  &value);
357   g_value_unset (&value);
358 
359   /* Season and Episode Number */
360   filter4 = gom_filter_new_and (filter1, filter2);
361   g_object_unref (filter1);
362   g_object_unref (filter2);
363 
364   /* Series ID and Season and Episode Number */
365   filter5 = gom_filter_new_and (filter3, filter4);
366   g_object_unref (filter3);
367   g_object_unref (filter4);
368 
369   resource = gom_repository_find_one_sync (repository,
370                                            EPISODE_TYPE_RESOURCE,
371                                            filter5,
372                                            &error);
373   g_assert_no_error (error);
374   g_assert (resource);
375   g_object_unref (filter5);
376   eres = EPISODE_RESOURCE (resource);
377 
378   g_object_get(eres,
379                EPISODE_COLUMN_SERIES_ID, &s1,
380                EPISODE_COLUMN_IMDB_ID, &s2,
381                NULL);
382   g_object_unref(eres);
383 
384   g_assert_cmpstr (s1, ==, values[0].series_id);
385   g_assert_cmpstr (s2, ==, values[0].imdb_id);
386   g_free (s1);
387   g_free (s2);
388 
389   free_memory_db (adapter, repository);
390 }
391 
392 /* Same as find_specific, but using the _full filter constructors */
393 static void
find_specific_and_full(void)394 find_specific_and_full (void)
395 {
396   GError *error = NULL;
397   GValue value = { 0, };
398   GomFilter *filter1, *filter2, *filter3, *filter4;
399   char *s1, *s2;
400   GomResource *resource;
401   EpisodeResource *eres;
402   GomAdapter *adapter;
403   GomRepository *repository;
404 
405   create_memory_db(&adapter, &repository);
406 
407   /* Season Number */
408   g_value_init(&value, G_TYPE_INT64);
409   g_value_set_int64(&value, values[0].season_number);
410   filter1 = gom_filter_new_eq(EPISODE_TYPE_RESOURCE,
411                                EPISODE_COLUMN_SEASON_NUMBER,
412                                &value);
413   g_value_unset(&value);
414 
415   /* Episode Number */
416   g_value_init(&value, G_TYPE_INT64);
417   g_value_set_int64(&value, values[0].episode_number);
418   filter2 = gom_filter_new_eq(EPISODE_TYPE_RESOURCE,
419                               EPISODE_COLUMN_EPISODE_NUMBER,
420                               &value);
421   g_value_unset(&value);
422 
423   /* Series ID */
424   g_value_init(&value, G_TYPE_STRING);
425   g_value_set_string(&value, values[0].series_id);
426   filter3 = gom_filter_new_like(EPISODE_TYPE_RESOURCE,
427                                 EPISODE_COLUMN_SERIES_ID,
428                                 &value);
429   g_value_unset(&value);
430 
431   /* Season Number and Episode Number and Series ID */
432   filter4 = gom_filter_new_and_full(filter1, filter2, filter3, NULL);
433   g_object_unref(filter1);
434   g_object_unref(filter2);
435   g_object_unref(filter3);
436 
437   resource = gom_repository_find_one_sync(repository,
438                                           EPISODE_TYPE_RESOURCE,
439                                           filter4,
440                                           &error);
441   g_assert_no_error(error);
442   g_assert(resource);
443   g_object_unref(filter4);
444   eres = EPISODE_RESOURCE(resource);
445 
446   g_object_get(eres,
447                EPISODE_COLUMN_SERIES_ID, &s1,
448                EPISODE_COLUMN_IMDB_ID, &s2,
449                NULL);
450   g_object_unref(eres);
451 
452   g_assert_cmpstr(s1, ==, values[0].series_id);
453   g_assert_cmpstr(s2, ==, values[0].imdb_id);
454   g_free(s1);
455   g_free(s2);
456 
457   free_memory_db(adapter, repository);
458 }
459 
460 /* Same as find_specific, but using the _fullv filter constructors */
461 static void
find_specific_and_fullv(void)462 find_specific_and_fullv (void)
463 {
464   GError *error = NULL;
465   GValue value = { 0, };
466   GomFilter **filter_array = g_new(GomFilter *, 4);
467   GomFilter *filter;
468   char *s1, *s2;
469   GomResource *resource;
470   EpisodeResource *eres;
471   GomAdapter *adapter;
472   GomRepository *repository;
473 
474   create_memory_db(&adapter, &repository);
475 
476   /* Season Number */
477   g_value_init(&value, G_TYPE_INT64);
478   g_value_set_int64(&value, values[0].season_number);
479   filter_array[0] = gom_filter_new_eq(EPISODE_TYPE_RESOURCE,
480                                       EPISODE_COLUMN_SEASON_NUMBER,
481                                       &value);
482   g_value_unset(&value);
483 
484   /* Episode Number */
485   g_value_init(&value, G_TYPE_INT64);
486   g_value_set_int64(&value, values[0].episode_number);
487   filter_array[1] = gom_filter_new_eq(EPISODE_TYPE_RESOURCE,
488                                       EPISODE_COLUMN_EPISODE_NUMBER,
489                                       &value);
490   g_value_unset(&value);
491 
492   /* Series ID */
493   g_value_init(&value, G_TYPE_STRING);
494   g_value_set_string(&value, values[0].series_id);
495   filter_array[2] = gom_filter_new_like(EPISODE_TYPE_RESOURCE,
496                                         EPISODE_COLUMN_SERIES_ID,
497                                         &value);
498   g_value_unset(&value);
499 
500   /* Season Number and Episode Number and Series ID */
501   filter_array[3] = NULL;
502   filter = gom_filter_new_and_fullv(filter_array);
503   g_object_unref(filter_array[0]);
504   g_object_unref(filter_array[1]);
505   g_object_unref(filter_array[2]);
506   g_free(filter_array);
507 
508   resource = gom_repository_find_one_sync(repository,
509                                           EPISODE_TYPE_RESOURCE,
510                                           filter,
511                                           &error);
512   g_assert_no_error(error);
513   g_assert(resource);
514   g_object_unref(filter);
515   eres = EPISODE_RESOURCE(resource);
516 
517   g_object_get(eres,
518                EPISODE_COLUMN_SERIES_ID, &s1,
519                EPISODE_COLUMN_IMDB_ID, &s2,
520                NULL);
521   g_object_unref(eres);
522 
523   g_assert_cmpstr(s1, ==, values[0].series_id);
524   g_assert_cmpstr(s2, ==, values[0].imdb_id);
525   g_free(s1);
526   g_free(s2);
527 
528   free_memory_db(adapter, repository);
529 }
530 
531 /* Ensure we respect filter priorities */
532 static void
find_specific_ensure_priorities(void)533 find_specific_ensure_priorities (void)
534 {
535    GomAdapter *adapter;
536    GomRepository *repository;
537    GomFilter *filter1, *filter2, *filter3, *filter4, *filter5;
538    GomResourceGroup *group;
539    GValue value = { 0, };
540    GError *error = NULL;
541    guint count;
542 
543    create_memory_db(&adapter, &repository);
544 
545    g_value_init(&value, G_TYPE_INT64);
546    g_value_set_int64(&value, 4);
547    filter1 = gom_filter_new_eq(EPISODE_TYPE_RESOURCE,
548                                EPISODE_COLUMN_SEASON_NUMBER, &value);
549    g_value_unset(&value);
550 
551    g_value_init(&value, G_TYPE_INT64);
552    g_value_set_int64(&value, 1);
553    filter2 = gom_filter_new_eq(EPISODE_TYPE_RESOURCE,
554                                EPISODE_COLUMN_EPISODE_NUMBER, &value);
555    g_value_unset(&value);
556 
557    g_value_init(&value, G_TYPE_INT64);
558    g_value_set_int64(&value, 2);
559    filter3 = gom_filter_new_eq(EPISODE_TYPE_RESOURCE,
560                                EPISODE_COLUMN_EPISODE_NUMBER, &value);
561    g_value_unset(&value);
562 
563    /* Search for:
564     *   ( season-number=4 AND episode-number=1 ) OR episode-number=2
565     */
566    filter4 = gom_filter_new_and_full(filter1, filter2, NULL);
567    filter5 = gom_filter_new_or_full(filter4, filter3, NULL);
568 
569    group = gom_repository_find_sync(repository, EPISODE_TYPE_RESOURCE,
570                                     filter5, &error);
571    g_assert_no_error(error);
572 
573    count = gom_resource_group_get_count(group);
574    g_assert_cmpuint(count, ==, 3);
575 
576    g_object_unref(filter4);
577    g_object_unref(filter5);
578 
579    /* Now search for:
580     *   season-number=4 AND ( episode-number=1 OR episode-number=2 )
581     */
582    filter4 = gom_filter_new_or_full(filter2, filter3, NULL);
583    filter5 = gom_filter_new_and_full(filter1, filter4, NULL);
584 
585    group = gom_repository_find_sync(repository, EPISODE_TYPE_RESOURCE,
586                                     filter5, &error);
587    g_assert_no_error(error);
588 
589    count = gom_resource_group_get_count(group);
590    g_assert_cmpuint(count, ==, 2);
591 
592    g_object_unref(filter1);
593    g_object_unref(filter2);
594    g_object_unref(filter3);
595    g_object_unref(filter4);
596    g_object_unref(filter5);
597 
598    free_memory_db(adapter, repository);
599 }
600 
601 static void
find_glob(void)602 find_glob (void)
603 {
604   GomAdapter *adapter;
605   GomRepository *repository;
606 
607   GValue value = { 0, };
608   GomFilter *filter;
609   GError *error = NULL;
610 
611   GomResource *resource;
612   EpisodeResource *eres;
613 
614   char *s1, *s2;
615 
616   create_memory_db (&adapter, &repository);
617 
618   g_value_init (&value, G_TYPE_STRING);
619   g_value_set_string (&value, "New York *");
620   filter = gom_filter_new_glob (EPISODE_TYPE_RESOURCE,
621                                 EPISODE_COLUMN_EPISODE_NAME,
622                                 &value);
623   g_value_unset (&value);
624 
625   resource = gom_repository_find_one_sync (repository,
626                                            EPISODE_TYPE_RESOURCE,
627                                            filter,
628                                            &error);
629   g_assert_no_error (error);
630   g_assert (resource);
631   g_object_unref (filter);
632   eres = EPISODE_RESOURCE (resource);
633 
634   g_object_get(eres,
635                EPISODE_COLUMN_SERIES_ID, &s1,
636                EPISODE_COLUMN_EPISODE_NAME, &s2,
637                NULL);
638   g_object_unref(eres);
639 
640   g_assert_cmpstr (s1, ==, values[0].series_id);
641   g_assert_cmpstr (s2, ==, values[0].episode_name);
642   g_free (s1);
643   g_free (s2);
644 
645   free_memory_db (adapter, repository);
646 }
647 
648 static void
find_null(void)649 find_null (void)
650 {
651   GError *error = NULL;
652   GValue value = { 0, };
653   GomFilter *filter1, *filter2, *filter3;
654   char *s1, *s2;
655   GomResource *resource;
656   EpisodeResource *eres;
657   GomAdapter *adapter;
658   GomRepository *repository;
659 
660   create_memory_db (&adapter, &repository);
661 
662   /* Season Number */
663   g_value_init (&value, G_TYPE_INT64);
664   g_value_set_int64 (&value, values[3].season_number);
665   filter1 = gom_filter_new_eq (EPISODE_TYPE_RESOURCE,
666                                EPISODE_COLUMN_SEASON_NUMBER,
667                                &value);
668   g_value_unset (&value);
669 
670   /* NULL name */
671   filter2 = gom_filter_new_is_null (EPISODE_TYPE_RESOURCE,
672                                     EPISODE_COLUMN_EPISODE_NAME);
673 
674   /* Season and NULL name */
675   filter3 = gom_filter_new_and (filter1, filter2);
676   g_object_unref (filter1);
677   g_object_unref (filter2);
678 
679   resource = gom_repository_find_one_sync (repository,
680                                            EPISODE_TYPE_RESOURCE,
681                                            filter3,
682                                            &error);
683   g_assert_no_error (error);
684   g_assert (resource);
685   g_object_unref (filter3);
686   eres = EPISODE_RESOURCE (resource);
687 
688   g_object_get(eres,
689                EPISODE_COLUMN_SERIES_ID, &s1,
690                EPISODE_COLUMN_IMDB_ID, &s2,
691                NULL);
692   g_object_unref(eres);
693 
694   g_assert_cmpstr (s1, ==, values[3].series_id);
695   g_assert_cmpstr (s2, ==, values[3].imdb_id);
696   g_free (s1);
697   g_free (s2);
698 
699   free_memory_db (adapter, repository);
700 }
701 
702 static void
find_not_null(void)703 find_not_null (void)
704 {
705   GError *error = NULL;
706   GValue value = { 0, };
707   GomFilter *filter1, *filter2, *filter3;
708   char *s1, *s2;
709   GomResource *resource;
710   EpisodeResource *eres;
711   GomAdapter *adapter;
712   GomRepository *repository;
713 
714   create_memory_db (&adapter, &repository);
715 
716   /* Season Number */
717   g_value_init (&value, G_TYPE_INT64);
718   g_value_set_int64 (&value, values[2].season_number);
719   filter1 = gom_filter_new_eq (EPISODE_TYPE_RESOURCE,
720                                EPISODE_COLUMN_SEASON_NUMBER,
721                                &value);
722   g_value_unset (&value);
723 
724   /* NULL name */
725   filter2 = gom_filter_new_is_not_null (EPISODE_TYPE_RESOURCE,
726                                         EPISODE_COLUMN_EPISODE_NAME);
727 
728   /* Season and NULL name */
729   filter3 = gom_filter_new_and (filter1, filter2);
730   g_object_unref (filter1);
731   g_object_unref (filter2);
732 
733   resource = gom_repository_find_one_sync (repository,
734                                            EPISODE_TYPE_RESOURCE,
735                                            filter3,
736                                            &error);
737   g_assert_no_error (error);
738   g_assert (resource);
739   g_object_unref (filter3);
740   eres = EPISODE_RESOURCE (resource);
741 
742   g_object_get(eres,
743                EPISODE_COLUMN_SERIES_ID, &s1,
744                EPISODE_COLUMN_IMDB_ID, &s2,
745                NULL);
746   g_object_unref(eres);
747 
748   g_assert_cmpstr (s1, ==, values[2].series_id);
749   g_assert_cmpstr (s2, ==, values[2].imdb_id);
750   g_free (s1);
751   g_free (s2);
752 
753   free_memory_db (adapter, repository);
754 }
755 
756 static void
find_sql(void)757 find_sql (void)
758 {
759   GomAdapter *adapter;
760   GomRepository *repository;
761 
762   GValue value = { 0, };
763   GArray *sql_values;
764   GomFilter *filter;
765   GError *error = NULL;
766 
767   GomResource *resource;
768   EpisodeResource *eres;
769 
770   char *s1, *s2;
771 
772   create_memory_db(&adapter, &repository);
773 
774   g_value_init(&value, G_TYPE_STRING);
775   g_value_set_string(&value, "New York Sour");
776   sql_values = g_array_new(FALSE, FALSE, sizeof(GValue));
777   g_array_append_val(sql_values, value);
778   filter = gom_filter_new_sql("'episodes'.'episode-name' == ?", sql_values);
779   g_value_unset(&value);
780   g_array_unref (sql_values);
781 
782   resource = gom_repository_find_one_sync(repository, EPISODE_TYPE_RESOURCE,
783                                           filter, &error);
784   g_assert_no_error(error);
785   g_assert(resource);
786   g_object_unref(filter);
787   eres = EPISODE_RESOURCE(resource);
788 
789   g_object_get(eres,
790                EPISODE_COLUMN_SERIES_ID, &s1,
791                EPISODE_COLUMN_EPISODE_NAME, &s2,
792                NULL);
793   g_object_unref(eres);
794 
795   g_assert_cmpstr(s1, ==, values[0].series_id);
796   g_assert_cmpstr(s2, ==, values[0].episode_name);
797   g_free(s1);
798   g_free(s2);
799 
800   free_memory_db(adapter, repository);
801 }
802 
803 gint
main(gint argc,gchar * argv[])804 main (gint argc, gchar *argv[])
805 {
806    g_test_init (&argc, &argv, NULL);
807    g_test_add_func ("/GomRepository/find-simple", find_simple);
808    g_test_add_func ("/GomRepository/find-specific", find_specific);
809    g_test_add_func ("/GomRepository/find-specific-and-full", find_specific_and_full);
810    g_test_add_func ("/GomRepository/find-specific-and-fullv", find_specific_and_fullv);
811    g_test_add_func ("/GomRepository/find-specific-ensure-priorities", find_specific_ensure_priorities);
812    g_test_add_func ("/GomRepository/find-glob", find_glob);
813    g_test_add_func ("/GomRepository/find-null", find_null);
814    g_test_add_func ("/GomRepository/find-not-null", find_not_null);
815    g_test_add_func ("/GomRepository/find-sql", find_sql);
816    gMainLoop = g_main_loop_new (NULL, FALSE);
817    return g_test_run ();
818 }
819