Statistics
| Revision:

root / trunk / tests / test_download_queue.c @ 1845

History | View | Annotate | Download (20 KB)

1
/* 
2
    Copyright (C) 2005-2011  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#include 
20
#include 
21
#include 
22

                
23
#include "common.h"
24
#include "nntpgrab_utils.h"
25
#include "download_queue.h"
26

                
27
static Configuration *config = NULL;
28

                
29
/* Fake placeholders */
30
void
31
ng_plugin_emit_log_msg(NGPlugin *plugin_data, NGLogLevel log_level, const char *format, ...)
32
{
33
    va_list args;
34
    char msg[1024];
35
    va_start(args, format);
36
    memset(msg, 0, sizeof(msg));
37
    vsnprintf(msg, sizeof(msg) - 1, format, args);
38
    va_end(args);
39

                
40
    g_test_message("%s", msg);
41
}
42

                
43
typedef void* DecoderData;
44
void
45
decoder_thread_push_task(DecoderData *task)
46
{
47

                
48
}
49

                
50
NntpgrabCore *
51
get_core(void)
52
{
53
    return NULL;
54
}
55

                
56
void
57
download_thread_awaken_if_needed(void)
58
{
59

                
60
}
61

                
62
ngboolean
63
ng_plugin_emit_internal_event(const char *event_name, ...)
64
{
65
    return TRUE;
66
}
67

                
68
/* Helper functions */
69
static NGList *
70
generate_part_list(guint64 *file_size)
71
{
72
    NNTPPart *part;
73
    NGList *list;
74

                
75
    g_return_val_if_fail(file_size != NULL, NULL);
76

                
77
    *file_size = 0;
78

                
79
    part = g_slice_new0(NNTPPart);
80
    strncpy((char *) part->message_id, "", sizeof(part->message_id));
81
    part->size = 258374;
82
    part->part_num = 1;
83
    *file_size += part->size;
84
    list = ng_list_append(NULL, part);
85

                
86
    part = g_slice_new0(NNTPPart);
87
    strncpy((char *) part->message_id, "", sizeof(part->message_id));
88
    part->size = 258436;
89
    part->part_num = 2;
90
    *file_size += part->size;
91
    list = ng_list_append(list, part);
92

                
93
    part = g_slice_new0(NNTPPart);
94
    strncpy((char *) part->message_id, "", sizeof(part->message_id));
95
    part->size = 258498;
96
    part->part_num = 3;
97
    *file_size += part->size;
98
    list = ng_list_append(list, part);
99

                
100
    part = g_slice_new0(NNTPPart);
101
    strncpy((char *) part->message_id, "", sizeof(part->message_id));
102
    part->size = 258448;
103
    part->part_num = 4;
104
    *file_size += part->size;
105
    list = ng_list_append(list, part);
106

                
107
    return list;
108
}
109

                
110
void
111
free_part_list(NGList *parts)
112
{
113
    NGList *list = parts;
114

                
115
    while (list) {
116
        g_slice_free(NNTPPart, list->data);
117
        list = ng_list_next(list);
118
    }
119

                
120
    ng_list_free(parts);
121
}
122

                
123
void
124
free_group_list(NGList *groups)
125
{
126
    NGList *list = groups;
127

                
128
    while (list) {
129
        g_free(list->data);
130
        list = ng_list_next(list);
131
    }
132

                
133
    ng_list_free(groups);
134
}
135

                
136
/* Testcases */
137
static void
138
test_download_queue_add_file_to_queue(void)
139
{
140
    char *errmsg = NULL;
141
    NGList *list_parts;
142
    NGList *list_groups;
143
    char *collection_name;
144
    char *subject;
145
    char *poster;
146
    time_t stamp;
147
    guint64 file_size = 0;
148

                
149
    GError *err = NULL;
150
    char *filename_expected;
151
    char *filename_real;
152
    char *contents_expected;
153
    char *contents_real;
154

                
155
    /* Add a single file to the download queue */
156
    collection_name = "some collection";
157
    subject = "some subject";
158
    poster = "some poster";
159
    stamp = 1185657196;
160

                
161
    list_parts = generate_part_list(&file_size);
162
    list_groups = ng_list_append(NULL, g_strdup("alt.binaries.x"));
163
    list_groups = ng_list_append(list_groups, g_strdup("alt.binaries.nl"));
164

                
165
    if (!download_queue_add_file_to_queue(collection_name, subject, poster, stamp, file_size, list_groups, list_parts, &errmsg)) {
166
        FAIL_TEST("Unable to add file to download queue: %s\n", errmsg);
167
    }
168

                
169
    free_part_list(list_parts);
170
    free_group_list(list_groups);
171

                
172
    if (!download_queue_save(&errmsg)) {
173
        FAIL_TEST("Unable to save download queue: %s\n", errmsg);
174
        g_free(errmsg);
175
        return;
176
    }
177

                
178
    /* Verify the contents of the download queue file */
179
    filename_expected = "download_queue_with_1_file.db";
180
    if (!g_file_get_contents(filename_expected, &contents_expected, NULL, &err)) {
181
        FAIL_TEST("Unable to read contents of '%s': %s\n", filename_expected, err->message);
182
        g_error_free(err);
183
        return;
184
    }
185

                
186
    filename_real = get_location_of_download_queue();
187
    if (!g_file_get_contents(filename_real, &contents_real, NULL, &err)) {
188
        FAIL_TEST("Unable to read contents of '%s': %s\n", filename_real, err->message);
189
        g_free(contents_expected);
190
        g_free(filename_real);
191
        g_error_free(err);
192
        return;
193
    }
194
    g_free(filename_real);
195

                
196
    g_assert_cmpstr(contents_expected, ==, contents_real);
197

                
198
    g_free(contents_expected);
199
    g_free(contents_real);
200
}
201

                
202
static void
203
test_download_queue_restart_file(void)
204
{
205
    char *collection_name;
206
    char *subject;
207
    char *errmsg = NULL;
208

                
209
    g_test_message("Now trying to restart file which was added in the add_item_to_queue testcase");
210
    collection_name = "some collection";
211
    subject = "some subject";
212
    if (!download_queue_restart_file(collection_name, subject, &errmsg)) {
213
        FAIL_TEST("Unable to remove file from download queue: %s\n", errmsg);
214
    }
215

                
216
    g_test_message("Now trying to restart a non-existant file");
217
    if (!download_queue_restart_file("non-existant", subject, &errmsg)) {
218
        /* This is good */
219
        g_free(errmsg);
220
    } else {
221
        FAIL_TEST("download_queue_restart_file returned TRUE, while FALSE was expected");
222
        return;
223
    }
224

                
225
    /* Verify the contents of the download queue file */
226

                
227
}
228

                
229
static void
230
test_download_queue_del_file_from_queue(void)
231
{
232
    char *collection_name;
233
    char *subject;
234
    char *errmsg = NULL;
235
    GError *err = NULL;
236
    char *filename_real;
237
    char *contents_real = NULL;
238

                
239
    g_test_message("Now trying to remove file which was added in the add_item_to_queue testcase");
240
    collection_name = "some collection";
241
    subject = "some subject";
242
    if (!download_queue_del_file_from_queue(collection_name, subject, &errmsg)) {
243
        FAIL_TEST("Unable to remove file from download queue: %s\n", errmsg);
244
        g_free(errmsg);
245
        return;
246
    }
247

                
248
    g_test_message("Now trying to remove a non-existant file");
249
    if (!download_queue_del_file_from_queue("non-existant", subject, &errmsg)) {
250
        /* This is good */
251
        g_free(errmsg);
252
    } else {
253
        FAIL_TEST("download_queue_del_file_from_queue returned TRUE, while FALSE was expected");
254
        return;
255
    }
256

                
257
    if (!download_queue_save(&errmsg)) {
258
        FAIL_TEST("Unable to save download queue: %s\n", errmsg);
259
        g_free(errmsg);
260
        return;
261
    }
262

                
263
    /* Verify the contents of the download queue file */
264
    filename_real = get_location_of_download_queue();
265
    if (!g_file_get_contents(filename_real, &contents_real, NULL, &err)) {
266
        FAIL_TEST("Unable to read contents of '%s': %s\n", filename_real, err->message);
267
        g_free(filename_real);
268
        g_error_free(err);
269
        return;
270
    }
271
    g_free(filename_real);
272

                
273
    g_assert_cmpstr("", ==, contents_real);
274

                
275
    g_free(contents_real);
276
}
277

                
278
static void
279
test_download_queue_get_next_part_to_download_setup(void *data, gconstpointer user_data)
280
{
281
    int i;
282
    char *errmsg = NULL;
283
    char *collection_name = "some collection";
284

                
285
    for (i = 1; i <= 10; i++) {
286
        char *subject;
287
        char *poster;
288
        time_t stamp;
289
        guint64 file_size = 0;
290
        NGList *list_parts;
291
        NGList *list_groups;
292

                
293
        subject = g_strdup_printf("file %i", i);
294
        poster = "some poster";
295
        stamp = 1185657196;
296

                
297
        list_parts = generate_part_list(&file_size);
298
        list_groups = ng_list_append(NULL, g_strdup("alt.binaries.x"));
299
        list_groups = ng_list_append(list_groups, g_strdup("alt.binaries.nl"));
300

                
301
        if (!download_queue_add_file_to_queue(collection_name, subject, poster, stamp, file_size, list_groups, list_parts, &errmsg)) {
302
            FAIL_TEST("Unable to add file to download queue: %s\n", errmsg);
303
            g_free(errmsg);
304
            return;
305
        }
306

                
307
        free_part_list(list_parts);
308
        free_group_list(list_groups);
309

                
310
        g_free(subject);
311
    }
312
}
313

                
314
static void
315
test_download_queue_get_next_part_to_download_setup_no_servers(void *data, gconstpointer user_data)
316
{
317
    g_assert(configuration_get_avail_servers(config) == NULL);
318

                
319
    test_download_queue_get_next_part_to_download_setup(data, user_data);
320
}
321

                
322
static void
323
test_download_queue_get_next_part_to_download_setup_one_server_before(void *data, gconstpointer user_data)
324
{
325
    char *errmsg = NULL;
326
    NGConfigServer server;
327

                
328
    g_assert(configuration_get_avail_servers(config) == NULL);
329

                
330
    memset(&server, 0, sizeof(server));
331
    strcpy(server.servername, "server1");
332
    strcpy(server.hostname, "host1");
333
    server.port = 119;
334
    server.enabled = TRUE;
335
    server.max_threads = 3;
336

                
337
    if (!configuration_add_server(config, server, &errmsg)) {
338
        FAIL_TEST("Unable to add server: %s\n", errmsg);
339
        g_free(errmsg);
340
        return;
341
    }
342

                
343
    test_download_queue_get_next_part_to_download_setup(data, user_data);
344
}
345

                
346
static void
347
test_download_queue_get_next_part_to_download_setup_one_server_after(void *data, gconstpointer user_data)
348
{
349
    char *errmsg = NULL;
350
    NGConfigServer server;
351

                
352
    g_assert(configuration_get_avail_servers(config) == NULL);
353

                
354
    memset(&server, 0, sizeof(server));
355
    strcpy(server.servername, "server1");
356
    strcpy(server.hostname, "host1");
357
    server.port = 119;
358
    server.enabled = TRUE;
359
    server.max_threads = 1;
360

                
361
    test_download_queue_get_next_part_to_download_setup(data, user_data);
362

                
363
    if (!configuration_add_server(config, server, &errmsg)) {
364
        FAIL_TEST("Unable to add server: %s\n", errmsg);
365
        g_free(errmsg);
366
        return;
367
    }
368
}
369

                
370
static void
371
test_download_queue_get_next_part_to_download_teardown(void *data, gconstpointer user_data)
372
{
373
    int i;
374
    char *errmsg = NULL;
375
    char *collection_name = "some collection";
376

                
377
    for (i = 1; i <= 10; i++) {
378
        char *subject;
379

                
380
        subject = g_strdup_printf("file %i", i);
381

                
382
        if (!download_queue_del_file_from_queue(collection_name, subject, &errmsg)) {
383
            FAIL_TEST("Unable to remove file from download queue: %s\n", errmsg);
384
            g_free(errmsg);
385
            return;
386
        }
387

                
388
        g_free(subject);
389
    }
390
}
391

                
392
static void
393
test_download_queue_get_next_part_to_download_teardown_no_servers(void *data, gconstpointer user_data)
394
{
395
    g_assert(configuration_get_avail_servers(config) == NULL);
396

                
397
    test_download_queue_get_next_part_to_download_teardown(data, user_data);
398
}
399

                
400
static void
401
test_download_queue_get_next_part_to_download_teardown_one_server(void *data, gconstpointer user_data)
402
{
403
    char *errmsg = NULL;
404

                
405
    g_assert(configuration_get_avail_servers(config) != NULL);
406

                
407
    test_download_queue_get_next_part_to_download_teardown(data, user_data);
408

                
409
    if (!configuration_del_server(config, "server1", &errmsg)) {
410
        FAIL_TEST("Unable to remove server: %s\n", errmsg);
411
        g_free(errmsg);
412
        return;
413
    }
414
}
415

                
416
static void
417
test_download_queue_get_next_part_to_download_no_servers(void *data, gconstpointer user_data)
418
{
419
    NNTPCollection *collection = NULL;
420
    NNTPFile *file = NULL;
421
    NNTPPart *part = NULL;
422
    gboolean nothing_to_download = FALSE;
423

                
424
    /* There are no servers configured at the moment, so a request for the next part for server_id 0 
425
     * should return FALSE and nothing_do_download should be TRUE */
426
    if (!download_queue_get_next_part_to_download(&collection, &file, &part, 0, ¬hing_to_download)) {
427
        g_assert_cmpint(nothing_to_download, ==, 1);
428
        g_assert(collection == NULL);
429
        g_assert(file == NULL);
430
        g_assert(part == NULL);
431
    } else {
432
        FAIL_TEST("download_queue_get_next_part_to_download returned TRUE while it isn't expected");
433
    }
434
}
435

                
436
static void
437
test_download_queue_get_next_part_to_download_one_server_generic(gboolean all_available)
438
{
439
    /* There should be 10 files with 4 parts each in the download queue now */
440
    int i, j;
441

                
442
    NNTPCollection *prev_collection = NULL;
443
    NNTPFile *prev_file = NULL;
444

                
445
    NNTPCollection *collection = NULL;
446
    NNTPFile *file = NULL;
447
    NNTPPart *part = NULL;
448
    gboolean nothing_to_download_or_active = FALSE;
449

                
450
    GList *list, *files = NULL;
451

                
452
    for (i = 1; i <= 10; i++) {
453
        prev_file = NULL;
454

                
455
        for (j = 1; j <= 4; j++) {
456
            /* There 1 server configured at the moment, so a request for the next part for server_id 0 
457
             * should return TRUE and nothing_do_download should_or_active be FALSE */
458
            if (!download_queue_get_next_part_to_download(&collection, &file, &part, 0, ¬hing_to_download_or_active)) {
459
                g_test_message("nothing_to_download = %i", nothing_to_download_or_active);
460
                FAIL_TEST("download_queue_get_next_part_to_download returned FALSE while it isn't expected");
461
                return;
462
            } else {
463
                char *expected_subject = g_strdup_printf("file %i", i);
464

                
465
                g_assert_cmpint(nothing_to_download_or_active, ==, FALSE);
466
                g_assert(collection != NULL);
467
                g_assert(file != NULL);
468
                g_assert(part != NULL);
469

                
470
                g_assert_cmpint(part->part_num, ==, j);
471
                g_assert_cmpstr(file->subject, ==, expected_subject);
472

                
473
                g_free(expected_subject);
474

                
475
                if (prev_collection == NULL) {
476
                    prev_collection = collection;
477
                } else {
478
                    g_assert(prev_collection == collection);
479
                }
480

                
481
                if (prev_file == NULL) {
482
                    prev_file = file;
483
                    files = g_list_append(files, file);
484
                } else {
485
                    g_assert(prev_file == file);
486
                }
487
            }
488

                
489
            /* Update the status of the part */
490
            if (!all_available && j % 2 == 0) {
491
                /* Indicate the every second part isn't available on the server and it shouldn't be retried again */
492
                download_queue_update_part_status("server1", 0, collection, file, part, 0, FALSE, FALSE, TRUE);
493
            } else {
494
                /* Indicate that the file was downloaded succesfully */
495
                download_queue_update_part_status("server1", 0, collection, file, part, 0, TRUE, FALSE, FALSE);
496
            }
497

                
498
            collection = NULL;
499
            file = NULL;
500
            part = NULL;
501
        }
502
    }
503

                
504
    /* We processed all files now. If we try to request another part it should indicate that there's nothing to download anymore */
505
    if (!download_queue_get_next_part_to_download(&collection, &file, &part, 0, ¬hing_to_download_or_active)) {
506
        /* Nothing is returned which is good */
507
        /* The flag nothing_to_download_or_active should be FALSE as all files are downloaded, but not decoded yet */
508
        g_assert_cmpint(nothing_to_download_or_active, ==, FALSE);
509
        g_assert(collection == NULL);
510
        g_assert(file == NULL);
511
        g_assert(part == NULL);
512
    } else {
513
        FAIL_TEST("download_queue_get_next_part_to_download returned TRUE while it isn't expected");
514
        return;
515
    }
516

                
517
    /* Mark all files as finished (downloaded+decoded) */
518
    list = files;
519
    while (list) {
520
        file = (NNTPFile*) list->data;
521

                
522
        if (!all_available && g_list_index(files, file) % 2 == 0) {
523
            /* Indicate that not all parts were available */
524
            download_queue_mark_file_as_decoded_and_unref(prev_collection, file, "somefilename", TASK_STATE_FINISHED_INCOMPLETE);
525
        } else {
526
            /* Indicate that all parts were decoded succesfully */
527
            download_queue_mark_file_as_decoded_and_unref(prev_collection, file, "somefilename", TASK_STATE_FINISHED_COMPLETE);
528
        }
529

                
530
        list = g_list_next(list);
531
    }
532
    g_list_free(files);
533

                
534
    /* Verify that nothing_to_download_or_active is TRUE now */
535
    if (!download_queue_get_next_part_to_download(&collection, &file, &part, 0, ¬hing_to_download_or_active)) {
536
        /* Nothing is returned which is good */
537
        g_assert_cmpint(nothing_to_download_or_active, ==, TRUE);
538
        g_assert(collection == NULL);
539
        g_assert(file == NULL);
540
        g_assert(part == NULL);
541
    } else {
542
        FAIL_TEST("download_queue_get_next_part_to_download returned TRUE while it isn't expected");
543
        return;
544
    }
545
}
546

                
547
static void
548
test_download_queue_get_next_part_to_download_one_server_all_available(void *data, gconstpointer user_data)
549
{
550
    /* Assume for this testcase that all parts are available on the server */
551
    test_download_queue_get_next_part_to_download_one_server_generic(TRUE);
552
}
553

                
554
static void
555
test_download_queue_get_next_part_to_download_one_server_some_available(void *data, gconstpointer user_data)
556
{
557
    /* Assume for this testcase that some parts are available on the server */
558
    test_download_queue_get_next_part_to_download_one_server_generic(FALSE);
559
}
560

                
561
int
562
main(int argc, char **argv)
563
{
564
    int ret;
565
    char *errmsg = NULL;
566

                
567
    g_type_init();
568
    g_test_init(&argc, &argv, NULL);
569
    g_test_bug_base("https://www.nntpgrab.nl/issues/");
570

                
571
    initialize_tests();
572

                
573
    /* Base initialisation for download queue operations */
574
    if (!(config = configuration_new(&errmsg, NULL))) {
575
        g_error("Unable to initialize configuration. Unable to continue download queue tests: %s\n", errmsg);
576
    }
577

                
578
    if (!download_queue_init(config, &errmsg)) {
579
        g_error("Unable to initialize download queue. Unable to continue download queue tests: %s\n", errmsg);
580
    }
581

                
582
    /* Add the various testcases */
583
    g_test_add_func("/download_queue/add_file_to_queue", test_download_queue_add_file_to_queue);
584
    g_test_add_func("/download_queue/restart_file", test_download_queue_restart_file);
585
    g_test_add_func("/download_queue/del_file_from_queue", test_download_queue_del_file_from_queue);
586
    g_test_add("/download_queue/get_next_part_to_download/no_servers", void, NULL,
587
               test_download_queue_get_next_part_to_download_setup_no_servers,
588
               test_download_queue_get_next_part_to_download_no_servers,
589
               test_download_queue_get_next_part_to_download_teardown_no_servers);
590
    g_test_add("/download_queue/get_next_part_to_download/one_server/before/all_available", void, NULL,
591
               test_download_queue_get_next_part_to_download_setup_one_server_before,
592
               test_download_queue_get_next_part_to_download_one_server_all_available,
593
               test_download_queue_get_next_part_to_download_teardown_one_server);
594
    g_test_add("/download_queue/get_next_part_to_download/one_server/after/all_available", void, NULL,
595
               test_download_queue_get_next_part_to_download_setup_one_server_after,
596
               test_download_queue_get_next_part_to_download_one_server_all_available,
597
               test_download_queue_get_next_part_to_download_teardown_one_server);
598
    g_test_add("/download_queue/get_next_part_to_download/one_server/before/some_available", void, NULL,
599
               test_download_queue_get_next_part_to_download_setup_one_server_before,
600
               test_download_queue_get_next_part_to_download_one_server_some_available,
601
               test_download_queue_get_next_part_to_download_teardown_one_server);
602
    g_test_add("/download_queue/get_next_part_to_download/one_server/after/some_available", void, NULL,
603
               test_download_queue_get_next_part_to_download_setup_one_server_after,
604
               test_download_queue_get_next_part_to_download_one_server_all_available,
605
               test_download_queue_get_next_part_to_download_teardown_one_server);
606

                
607
    /* Perform the tests */
608
    ret = g_test_run();
609

                
610
    /* Cleanup */
611
    if (!download_queue_destroy(&errmsg)) {
612
        g_error("Unable to destroy download queue: %s\n", &errmsg);
613
    }
614

                
615
    configuration_destroy(config);
616

                
617
    cleanup_tests();
618

                
619
    return ret;
620
}