~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

Viewing changes to storage/tokudb/ft-index/ft/tests/ftloader-test.cc

  • Committer: Package Import Robot
  • Author(s): James Page, Otto Kekäläinen
  • Date: 2014-02-17 16:51:52 UTC
  • mfrom: (2.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20140217165152-k315d3175g865kkx
Tags: 5.5.35-1
[ Otto Kekäläinen ]
* New upstream release, fixing the following security issues:
  - Buffer overflow in client/mysql.cc (Closes: #737597).
    - CVE-2014-0001
  - http://www.oracle.com/technetwork/topics/security/cpujan2014-1972949.html
    - CVE-2013-5891
    - CVE-2013-5908
    - CVE-2014-0386
    - CVE-2014-0393
    - CVE-2014-0401
    - CVE-2014-0402
    - CVE-2014-0412
    - CVE-2014-0420
    - CVE-2014-0437
* Upstream https://mariadb.atlassian.net/browse/MDEV-4902
  fixes compatibility with Bison 3.0 (Closes: #733002)
* Updated Russian debconf translation (Closes: #734426)
* Updated Japanese debconf translation (Closes: #735284)
* Updated French debconf translation (Closes: #736480)
* Renamed SONAME properly (Closes: #732967)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 
2
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
 
3
#ident "$Id$"
 
4
/*
 
5
COPYING CONDITIONS NOTICE:
 
6
 
 
7
  This program is free software; you can redistribute it and/or modify
 
8
  it under the terms of version 2 of the GNU General Public License as
 
9
  published by the Free Software Foundation, and provided that the
 
10
  following conditions are met:
 
11
 
 
12
      * Redistributions of source code must retain this COPYING
 
13
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
 
14
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
 
15
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
 
16
        GRANT (below).
 
17
 
 
18
      * Redistributions in binary form must reproduce this COPYING
 
19
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
 
20
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
 
21
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
 
22
        GRANT (below) in the documentation and/or other materials
 
23
        provided with the distribution.
 
24
 
 
25
  You should have received a copy of the GNU General Public License
 
26
  along with this program; if not, write to the Free Software
 
27
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
28
  02110-1301, USA.
 
29
 
 
30
COPYRIGHT NOTICE:
 
31
 
 
32
  TokuDB, Tokutek Fractal Tree Indexing Library.
 
33
  Copyright (C) 2007-2013 Tokutek, Inc.
 
34
 
 
35
DISCLAIMER:
 
36
 
 
37
  This program is distributed in the hope that it will be useful, but
 
38
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
39
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
40
  General Public License for more details.
 
41
 
 
42
UNIVERSITY PATENT NOTICE:
 
43
 
 
44
  The technology is licensed by the Massachusetts Institute of
 
45
  Technology, Rutgers State University of New Jersey, and the Research
 
46
  Foundation of State University of New York at Stony Brook under
 
47
  United States of America Serial No. 11/760379 and to the patents
 
48
  and/or patent applications resulting from it.
 
49
 
 
50
PATENT MARKING NOTICE:
 
51
 
 
52
  This software is covered by US Patent No. 8,185,551.
 
53
  This software is covered by US Patent No. 8,489,638.
 
54
 
 
55
PATENT RIGHTS GRANT:
 
56
 
 
57
  "THIS IMPLEMENTATION" means the copyrightable works distributed by
 
58
  Tokutek as part of the Fractal Tree project.
 
59
 
 
60
  "PATENT CLAIMS" means the claims of patents that are owned or
 
61
  licensable by Tokutek, both currently or in the future; and that in
 
62
  the absence of this license would be infringed by THIS
 
63
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
 
64
 
 
65
  "PATENT CHALLENGE" shall mean a challenge to the validity,
 
66
  patentability, enforceability and/or non-infringement of any of the
 
67
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
 
68
 
 
69
  Tokutek hereby grants to you, for the term and geographical scope of
 
70
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
 
71
  irrevocable (except as stated in this section) patent license to
 
72
  make, have made, use, offer to sell, sell, import, transfer, and
 
73
  otherwise run, modify, and propagate the contents of THIS
 
74
  IMPLEMENTATION, where such license applies only to the PATENT
 
75
  CLAIMS.  This grant does not include claims that would be infringed
 
76
  only as a consequence of further modifications of THIS
 
77
  IMPLEMENTATION.  If you or your agent or licensee institute or order
 
78
  or agree to the institution of patent litigation against any entity
 
79
  (including a cross-claim or counterclaim in a lawsuit) alleging that
 
80
  THIS IMPLEMENTATION constitutes direct or contributory patent
 
81
  infringement, or inducement of patent infringement, then any rights
 
82
  granted to you under this License shall terminate as of the date
 
83
  such litigation is filed.  If you or your agent or exclusive
 
84
  licensee institute or order or agree to the institution of a PATENT
 
85
  CHALLENGE, then Tokutek may terminate any rights granted to you
 
86
  under this License.
 
87
*/
 
88
 
 
89
#ident "Copyright (c) 2010-2013 Tokutek Inc.  All rights reserved."
 
90
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
 
91
 
 
92
#include "test.h"
 
93
#include <toku_assert.h>
 
94
#include <string.h>
 
95
#include <stdio.h>
 
96
#include <unistd.h>
 
97
#include "ftloader-internal.h"
 
98
#include "memory.h"
 
99
#include <portability/toku_path.h>
 
100
 
 
101
 
 
102
static int qsort_compare_ints (const void *a, const void *b) {
 
103
    int avalue = *(int*)a;
 
104
    int bvalue = *(int*)b;
 
105
    if (avalue<bvalue) return -1;
 
106
    if (avalue>bvalue) return +1;
 
107
    return 0;
 
108
 
 
109
}
 
110
 
 
111
static int compare_ints (DB* UU(desc), const DBT *akey, const DBT *bkey) {
 
112
    assert(akey->size==sizeof(int));
 
113
    assert(bkey->size==sizeof(int));
 
114
    return qsort_compare_ints(akey->data, bkey->data);
 
115
}
 
116
 
 
117
static void err_cb(DB *db UU(), int dbn UU(), int err UU(), DBT *key UU(), DBT *val UU(), void *extra UU()) {
 
118
    fprintf(stderr, "error in test");
 
119
    abort();
 
120
}
 
121
 
 
122
bool founddup;
 
123
static void expect_dups_cb(DB *db UU(), int dbn UU(), int err UU(), DBT *key UU(), DBT *val UU(), void *extra UU()) {
 
124
    founddup=true;
 
125
}
 
126
 
 
127
static void test_merge_internal (int a[], int na, int b[], int nb, bool dups) {
 
128
    int *MALLOC_N(na+nb, ab); // the combined array a and b
 
129
    for (int i=0; i<na; i++) {
 
130
        ab[i]=a[i];
 
131
    }
 
132
    for (int i=0; i<nb; i++) {
 
133
        ab[na+i] = b[i];
 
134
    }
 
135
    struct row *MALLOC_N(na, ar);
 
136
    struct row *MALLOC_N(nb, br);
 
137
    for (int i=0; i<na; i++) {
 
138
        ar[i].off = i*sizeof(a[0]);
 
139
        ar[i].klen = sizeof(a[i]);
 
140
        ar[i].vlen = 0;
 
141
    }
 
142
    for (int i=0; i<nb; i++) {
 
143
        br[i].off  = (na+i)*sizeof(b[0]);
 
144
        br[i].klen = sizeof(b[i]);
 
145
        br[i].vlen = 0;
 
146
    }
 
147
    struct row *MALLOC_N(na+nb, cr);
 
148
    DB *dest_db = NULL;
 
149
    struct ft_loader_s bl;
 
150
    ft_loader_init_error_callback(&bl.error_callback);
 
151
    ft_loader_set_error_function(&bl.error_callback, dups ? expect_dups_cb : err_cb, NULL);
 
152
    struct rowset rs = { .memory_budget = 0, .n_rows = 0, .n_rows_limit = 0, .rows = NULL, .n_bytes = 0, .n_bytes_limit = 0,
 
153
                         .data=(char*)ab};
 
154
    merge_row_arrays_base(cr, ar, na, br, nb, 0, dest_db, compare_ints, &bl, &rs);
 
155
    ft_loader_call_error_function(&bl.error_callback);
 
156
    if (dups) {
 
157
        assert(founddup);
 
158
    } else {
 
159
        // verify the merge
 
160
        int i=0;
 
161
        int j=0;
 
162
        for (int k=0; k<na+nb; k++) {
 
163
            int voff = cr[k].off;
 
164
            int vc   = *(int*)(((char*)ab)+voff);
 
165
            if (i<na && j<nb) {
 
166
                if (vc==a[i]) {
 
167
                    assert(a[i]<=b[j]);
 
168
                    i++;
 
169
                } else if (vc==b[j]) {
 
170
                    assert(a[i]>b[j]);
 
171
                    j++;
 
172
                } else {
 
173
                    assert(0);
 
174
                }
 
175
            }
 
176
        }
 
177
    }
 
178
    toku_free(cr);
 
179
    toku_free(ar);
 
180
    toku_free(br);
 
181
    toku_free(ab);
 
182
    ft_loader_destroy_error_callback(&bl.error_callback);
 
183
}
 
184
 
 
185
/* Test the basic merger. */
 
186
static void test_merge (void) {
 
187
    {
 
188
        int avals[]={1,2,3,4,5};
 
189
        int *bvals = NULL; //icc won't let us use a zero-sized array explicitly or by [] = {} construction.
 
190
        test_merge_internal(avals, 5, bvals, 0, false);
 
191
        test_merge_internal(bvals, 0, avals, 5, false);
 
192
    }
 
193
    {
 
194
        int avals[]={1,3,5,7};
 
195
        int bvals[]={2,4};
 
196
        test_merge_internal(avals, 4, bvals, 2, false);
 
197
        test_merge_internal(bvals, 2, avals, 4, false);
 
198
    }
 
199
    {
 
200
        int avals[]={1,2,3,5,6,7};
 
201
        int bvals[]={2,4,5,6,8};
 
202
        test_merge_internal(avals, 6, bvals, 5, true);
 
203
        test_merge_internal(bvals, 5, avals, 6, true);
 
204
    }
 
205
}
 
206
 
 
207
static void test_internal_mergesort_row_array (int a[], int n) {
 
208
    struct row *MALLOC_N(n, ar);
 
209
    for (int i=0; i<n; i++) {
 
210
        ar[i].off  = i*sizeof(a[0]);
 
211
        ar[i].klen = sizeof(a[i]);
 
212
        ar[i].vlen = 0;
 
213
    }
 
214
    struct rowset rs = { .memory_budget = 0, .n_rows = 0, .n_rows_limit = 0, .rows = NULL, .n_bytes = 0, .n_bytes_limit = 0,
 
215
                         .data=(char*)a};
 
216
    ft_loader_mergesort_row_array (ar, n, 0, NULL, compare_ints, NULL, &rs);
 
217
    int *MALLOC_N(n, tmp);
 
218
    for (int i=0; i<n; i++) {
 
219
        tmp[i]=a[i];
 
220
    }
 
221
    qsort(tmp, n, sizeof(a[0]), qsort_compare_ints);
 
222
    for (int i=0; i<n; i++) {
 
223
        int voff = ar[i].off;
 
224
        int v    = *(int*)(((char*)a)+voff);
 
225
        assert(tmp[i]==v);
 
226
    }
 
227
    toku_free(ar);
 
228
    toku_free(tmp);
 
229
}
 
230
 
 
231
static void test_mergesort_row_array (void) {
 
232
    {
 
233
        int avals[]={5,2,1,7};
 
234
        for (int i=0; i<=4; i++)
 
235
            test_internal_mergesort_row_array(avals, i);
 
236
    }
 
237
    const int MAX_LEN = 100;
 
238
    enum { MAX_VAL = 1000 };
 
239
    for (int i=0; i<MAX_LEN; i++) {
 
240
        bool used[MAX_VAL];
 
241
        for (int j=0; j<MAX_VAL; j++) used[j]=false; 
 
242
        int len=1+random()%MAX_LEN;
 
243
        int avals[len];
 
244
        for (int j=0; j<len; j++) {
 
245
            int v;
 
246
            do {
 
247
                v = random()%MAX_VAL;
 
248
            } while (used[v]); 
 
249
            avals[j] = v;
 
250
            used[v] = true;
 
251
        }
 
252
        test_internal_mergesort_row_array(avals, len);
 
253
    }
 
254
}
 
255
 
 
256
static void test_read_write_rows (char *tf_template) {
 
257
    struct ft_loader_s bl;
 
258
    ZERO_STRUCT(bl);
 
259
    bl.temp_file_template = tf_template;
 
260
    int r = ft_loader_init_file_infos(&bl.file_infos);
 
261
    CKERR(r);
 
262
    FIDX file;
 
263
    r = ft_loader_open_temp_file(&bl, &file);
 
264
    CKERR(r);
 
265
 
 
266
    uint64_t dataoff=0;
 
267
 
 
268
    const char *keystrings[] = {"abc", "b", "cefgh"};
 
269
    const char *valstrings[] = {"defg", "", "xyz"};
 
270
    uint64_t actual_size=0;
 
271
    for (int i=0; i<3; i++) {
 
272
        DBT key;
 
273
        toku_fill_dbt(&key, keystrings[i], strlen(keystrings[i]));
 
274
        DBT val;
 
275
        toku_fill_dbt(&val, valstrings[i], strlen(valstrings[i]));
 
276
        r = loader_write_row(&key, &val, file, toku_bl_fidx2file(&bl, file), &dataoff, nullptr, &bl);
 
277
        CKERR(r);
 
278
        actual_size+=key.size + val.size + 8;
 
279
    }
 
280
    if (actual_size != dataoff) fprintf(stderr, "actual_size=%" PRIu64 ", dataoff=%" PRIu64 "\n", actual_size, dataoff);
 
281
    assert(actual_size == dataoff);
 
282
 
 
283
    r = ft_loader_fi_close(&bl.file_infos, file, true);
 
284
    CKERR(r);
 
285
 
 
286
    r = ft_loader_fi_reopen(&bl.file_infos, file, "r");
 
287
    CKERR(r);
 
288
 
 
289
    {
 
290
        int n_read=0;
 
291
        DBT key, val;
 
292
        toku_init_dbt(&key);
 
293
        toku_init_dbt(&val);
 
294
        while (0==loader_read_row(toku_bl_fidx2file(&bl, file), &key, &val)) {
 
295
            assert(strlen(keystrings[n_read])==key.size);
 
296
            assert(strlen(valstrings[n_read])==val.size);
 
297
            assert(0==memcmp(keystrings[n_read], key.data, key.size));
 
298
            assert(0==memcmp(valstrings[n_read], val.data, val.size));
 
299
            assert(key.size<=key.ulen);
 
300
            assert(val.size<=val.ulen);
 
301
            n_read++;
 
302
        }
 
303
        assert(n_read==3);
 
304
        toku_free(key.data);
 
305
        toku_free(val.data);
 
306
    }
 
307
    r = ft_loader_fi_close(&bl.file_infos, file, true);
 
308
    CKERR(r);
 
309
 
 
310
    r = ft_loader_fi_unlink(&bl.file_infos, file);
 
311
    CKERR(r);
 
312
 
 
313
    assert(bl.file_infos.n_files_open==0);
 
314
    assert(bl.file_infos.n_files_extant==0);
 
315
 
 
316
    ft_loader_fi_destroy(&bl.file_infos, false);
 
317
}
 
318
 
 
319
static void fill_rowset (struct rowset *rows,
 
320
                         int keys[],
 
321
                         const char *vals[],
 
322
                         int n,
 
323
                         uint64_t *size_est) {
 
324
    init_rowset(rows, toku_ft_loader_get_rowset_budget_for_testing());
 
325
    for (int i=0; i<n; i++) {
 
326
        DBT key;
 
327
        toku_fill_dbt(&key, &keys[i], sizeof keys[i]);
 
328
        DBT val;
 
329
        toku_fill_dbt(&val, vals[i], strlen(vals[i]));
 
330
        add_row(rows, &key, &val);
 
331
        *size_est += ft_loader_leafentry_size(key.size, val.size, TXNID_NONE);
 
332
    }
 
333
}
 
334
 
 
335
static void verify_dbfile(int n, int sorted_keys[], const char *sorted_vals[], const char *name) {
 
336
    int r;
 
337
 
 
338
    CACHETABLE ct;
 
339
    toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
 
340
 
 
341
    TOKUTXN const null_txn = NULL;
 
342
    FT_HANDLE t = NULL;
 
343
    toku_ft_handle_create(&t);
 
344
    toku_ft_set_bt_compare(t, compare_ints);
 
345
    r = toku_ft_handle_open(t, name, 0, 0, ct, null_txn); assert(r==0);
 
346
 
 
347
    FT_CURSOR cursor = NULL;
 
348
    r = toku_ft_cursor(t, &cursor, NULL, false, false); assert(r == 0);
 
349
 
 
350
    size_t userdata = 0;
 
351
    int i;
 
352
    for (i=0; i<n; i++) {
 
353
        struct check_pair pair = {sizeof sorted_keys[i], &sorted_keys[i], (ITEMLEN) strlen(sorted_vals[i]), sorted_vals[i], 0};
 
354
        r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
 
355
        if (r != 0) {
 
356
            assert(pair.call_count ==0);
 
357
            break;
 
358
        }
 
359
        assert(pair.call_count==1);
 
360
        userdata += pair.keylen + pair.vallen;
 
361
    }
 
362
    
 
363
    struct check_pair pair; memset(&pair, 0, sizeof pair);
 
364
    r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_NEXT);
 
365
    assert(r != 0);
 
366
 
 
367
    toku_ft_cursor_close(cursor);
 
368
 
 
369
    struct ftstat64_s s;
 
370
    toku_ft_handle_stat64(t, NULL, &s);
 
371
    assert(s.nkeys == (uint64_t) n && s.ndata == (uint64_t) n && s.dsize == userdata);
 
372
    
 
373
    r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
 
374
    toku_cachetable_close(&ct);
 
375
}
 
376
 
 
377
static void test_merge_files (const char *tf_template, const char *output_name) {
 
378
    DB *dest_db = NULL;
 
379
    struct ft_loader_s bl;
 
380
    ZERO_STRUCT(bl);
 
381
    bl.temp_file_template = tf_template;
 
382
    bl.reserved_memory = 512*1024*1024;
 
383
    int r = ft_loader_init_file_infos(&bl.file_infos); CKERR(r);
 
384
    ft_loader_lock_init(&bl);
 
385
    ft_loader_init_error_callback(&bl.error_callback);
 
386
    ft_loader_set_fractal_workers_count_from_c(&bl);
 
387
 
 
388
    struct merge_fileset fs;
 
389
    init_merge_fileset(&fs);
 
390
 
 
391
    int a_keys[] = {   1,    3,    5,    7, 8, 9};
 
392
    int b_keys[] = { 0,   2,    4,    6         };
 
393
    const char *a_vals[] = {"a", "c", "e", "g", "h", "i"};
 
394
    const char *b_vals[] = {"0", "b", "d", "f"};
 
395
    int sorted_keys[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
396
    const char *sorted_vals[] = { "0", "a", "b", "c", "d", "e", "f", "g", "h", "i" };
 
397
    struct rowset aset, bset;
 
398
    uint64_t size_est = 0;
 
399
    fill_rowset(&aset, a_keys, a_vals, 6, &size_est);
 
400
    fill_rowset(&bset, b_keys, b_vals, 4, &size_est);
 
401
 
 
402
    toku_ft_loader_set_n_rows(&bl, 6+4);
 
403
 
 
404
    ft_loader_set_error_function(&bl.error_callback, err_cb, NULL);
 
405
    r = ft_loader_sort_and_write_rows(&aset, &fs, &bl, 0, dest_db, compare_ints);  CKERR(r);
 
406
    r = ft_loader_sort_and_write_rows(&bset, &fs, &bl, 0, dest_db, compare_ints);  CKERR(r);
 
407
    assert(fs.n_temp_files==2 && fs.n_temp_files_limit >= fs.n_temp_files);
 
408
    // destroy_rowset(&aset);
 
409
    // destroy_rowset(&bset);
 
410
    for (int i=0; i<2; i++) assert(fs.data_fidxs[i].idx != -1);
 
411
 
 
412
    ft_loader_fi_close_all(&bl.file_infos);
 
413
 
 
414
    QUEUE q;
 
415
    r = queue_create(&q, 0xFFFFFFFF); // infinite queue.
 
416
    assert(r==0);
 
417
 
 
418
    r = merge_files(&fs, &bl, 0, dest_db, compare_ints, 0, q); CKERR(r);
 
419
 
 
420
    assert(fs.n_temp_files==0);
 
421
 
 
422
    DESCRIPTOR_S desc;
 
423
    toku_fill_dbt(&desc.dbt, "abcd", 4);
 
424
 
 
425
    int fd = open(output_name, O_RDWR | O_CREAT | O_BINARY, S_IRWXU|S_IRWXG|S_IRWXO);
 
426
    assert(fd>=0);
 
427
    
 
428
    r = toku_loader_write_brt_from_q_in_C(&bl, &desc, fd, 1000, q, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD);
 
429
    assert(r==0);
 
430
 
 
431
    destroy_merge_fileset(&fs);
 
432
    ft_loader_fi_destroy(&bl.file_infos, false);
 
433
    ft_loader_destroy_error_callback(&bl.error_callback);
 
434
    ft_loader_lock_destroy(&bl);
 
435
 
 
436
    // verify the dbfile
 
437
    verify_dbfile(10, sorted_keys, sorted_vals, output_name);
 
438
 
 
439
    r = queue_destroy(q);
 
440
    assert(r==0);
 
441
}
 
442
 
 
443
/* Test to see if we can open temporary files. */
 
444
int test_main (int argc, const char *argv[]) {
 
445
    argc--; argv++;
 
446
    while (argc>0) {
 
447
        if (strcmp(argv[0],"-v")==0) {
 
448
            verbose=1;
 
449
        } else if (strcmp(argv[0],"-q")==0) {
 
450
            verbose=0;
 
451
        }
 
452
        else {
 
453
            break;
 
454
        }
 
455
        argc--; argv++;
 
456
    }
 
457
    const char* directory = TOKU_TEST_FILENAME;
 
458
    int r = toku_os_mkdir(directory, 0755);
 
459
    if (r!=0) CKERR2(errno, EEXIST);
 
460
 
 
461
    int  templen = strlen(directory)+15;
 
462
    char tf_template[templen];
 
463
    {
 
464
        int n = snprintf(tf_template, templen, "%s/tempXXXXXX", directory);
 
465
        assert (n>0 && n<templen);
 
466
    }
 
467
    char output_name[templen];
 
468
    {
 
469
        int n = snprintf(output_name, templen, "%s/data.tokudb", directory);
 
470
        assert (n>0 && n<templen);
 
471
    }
 
472
    test_read_write_rows(tf_template);
 
473
    test_merge();
 
474
    test_mergesort_row_array();
 
475
    test_merge_files(tf_template, output_name);
 
476
    
 
477
    {
 
478
        char deletecmd[templen];
 
479
        int n =  snprintf(deletecmd, templen, "rm -rf %s", directory);
 
480
        assert(n>0 && n<templen);
 
481
        r = system(deletecmd);
 
482
        CKERR(r);
 
483
    }
 
484
 
 
485
    return 0;
 
486
}
 
487