~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/test-leafentry-nested.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) 2007-2013 Tokutek Inc.  All rights reserved."
 
90
#include <toku_portability.h>
 
91
#include <string.h>
 
92
 
 
93
#include "test.h"
 
94
#include "fttypes.h"
 
95
 
 
96
#include "ule.h"
 
97
#include "ule-internal.h"
 
98
 
 
99
enum {MAX_SIZE = 256};
 
100
static XIDS nested_xids[MAX_TRANSACTION_RECORDS];
 
101
 
 
102
static void
 
103
verify_ule_equal(ULE a, ULE b) {
 
104
    assert(a->num_cuxrs > 0);
 
105
    assert(a->num_puxrs < MAX_TRANSACTION_RECORDS);
 
106
    assert(a->num_cuxrs == b->num_cuxrs);
 
107
    assert(a->num_puxrs == b->num_puxrs);
 
108
    uint32_t i;
 
109
    for (i = 0; i < (a->num_cuxrs + a->num_puxrs); i++) {
 
110
        assert(a->uxrs[i].type == b->uxrs[i].type);
 
111
        assert(a->uxrs[i].xid  == b->uxrs[i].xid);
 
112
        if (a->uxrs[i].type == XR_INSERT) {
 
113
            assert(a->uxrs[i].vallen  == b->uxrs[i].vallen);
 
114
            assert(memcmp(a->uxrs[i].valp, b->uxrs[i].valp, a->uxrs[i].vallen) == 0);
 
115
        }
 
116
    }
 
117
}
 
118
 
 
119
static void
 
120
verify_le_equal(LEAFENTRY a, LEAFENTRY b) {
 
121
    if (a==NULL) assert(b==NULL);
 
122
    else {
 
123
        assert(b!=NULL);
 
124
 
 
125
        size_t size = leafentry_memsize(a);
 
126
        assert(size==leafentry_memsize(b));
 
127
 
 
128
        assert(memcmp(a, b, size) == 0);
 
129
 
 
130
        ULE_S ule_a;
 
131
        ULE_S ule_b;
 
132
 
 
133
        le_unpack(&ule_a, a);
 
134
        le_unpack(&ule_b, b);
 
135
        verify_ule_equal(&ule_a, &ule_b);
 
136
        ule_cleanup(&ule_a);
 
137
        ule_cleanup(&ule_b);
 
138
    }
 
139
}
 
140
 
 
141
static void
 
142
fillrandom(uint8_t buf[MAX_SIZE], uint32_t length) {
 
143
    assert(length < MAX_SIZE);
 
144
    uint32_t i;
 
145
    for (i = 0; i < length; i++) {
 
146
        buf[i] = random() & 0xFF;
 
147
    } 
 
148
}
 
149
 
 
150
static void
 
151
test_le_offset_is(LEAFENTRY le, void *field, size_t expected_offset) {
 
152
    size_t le_address    = (size_t) le;
 
153
    size_t field_address = (size_t) field;
 
154
    assert(field_address >= le_address);
 
155
    size_t actual_offset = field_address - le_address;
 
156
    assert(actual_offset == expected_offset);
 
157
}
 
158
 
 
159
//Fixed offsets in a packed leafentry.
 
160
enum {
 
161
    LE_OFFSET_NUM      = 0,
 
162
    LE_OFFSET_VARIABLE = 1+LE_OFFSET_NUM
 
163
};
 
164
 
 
165
static void
 
166
test_le_fixed_offsets (void) {
 
167
    LEAFENTRY XMALLOC(le);
 
168
    test_le_offset_is(le, &le->type,                       LE_OFFSET_NUM);
 
169
    toku_free(le);
 
170
}
 
171
 
 
172
//Fixed offsets in a leafentry with no uncommitted transaction records.
 
173
//(Note, there is no type required.) 
 
174
enum {
 
175
    LE_COMMITTED_OFFSET_VALLEN = LE_OFFSET_VARIABLE,
 
176
    LE_COMMITTED_OFFSET_VAL    = 4 + LE_COMMITTED_OFFSET_VALLEN
 
177
};
 
178
 
 
179
static void
 
180
test_le_committed_offsets (void) {
 
181
    LEAFENTRY XMALLOC(le);
 
182
    test_le_offset_is(le, &le->u.clean.vallen, LE_COMMITTED_OFFSET_VALLEN);
 
183
    test_le_offset_is(le, &le->u.clean.val, LE_COMMITTED_OFFSET_VAL);
 
184
    toku_free(le);
 
185
}
 
186
 
 
187
//Fixed offsets in a leafentry with uncommitted transaction records.
 
188
enum {
 
189
    LE_MVCC_OFFSET_NUM_CUXRS   =  LE_OFFSET_VARIABLE, //Type of innermost record
 
190
    LE_MVCC_OFFSET_NUM_PUXRS    = 4+LE_MVCC_OFFSET_NUM_CUXRS, //XID of outermost noncommitted record
 
191
    LE_MVCC_OFFSET_XRS    = 1+LE_MVCC_OFFSET_NUM_PUXRS
 
192
};
 
193
 
 
194
static void
 
195
test_le_provisional_offsets (void) {
 
196
    LEAFENTRY XMALLOC(le);
 
197
    test_le_offset_is(le, &le->u.mvcc.num_cxrs,            LE_MVCC_OFFSET_NUM_CUXRS);
 
198
    test_le_offset_is(le, &le->u.mvcc.num_pxrs, LE_MVCC_OFFSET_NUM_PUXRS);
 
199
    test_le_offset_is(le, &le->u.mvcc.xrs,               LE_MVCC_OFFSET_XRS);
 
200
    toku_free(le);
 
201
}
 
202
 
 
203
//We use a packed struct to represent a leafentry.
 
204
//We want to make sure the compiler correctly represents the offsets.
 
205
//This test verifies all offsets in a packed leafentry correspond to the required memory format.
 
206
static void
 
207
test_le_offsets (void) {
 
208
    test_le_fixed_offsets();
 
209
    test_le_committed_offsets();
 
210
    test_le_provisional_offsets();
 
211
}
 
212
 
 
213
static void
 
214
test_ule_packs_to_nothing (ULE ule) {
 
215
    LEAFENTRY le;
 
216
    int r = le_pack(ule, NULL, 0, NULL, 0, 0, &le);
 
217
    assert(r==0);
 
218
    assert(le==NULL);
 
219
}
 
220
 
 
221
//A leafentry must contain at least one 'insert' (all deletes means the leafentry
 
222
//should not exist).
 
223
//Verify that 'le_pack' of any set of all deletes ends up not creating a leafentry.
 
224
static void
 
225
test_le_empty_packs_to_nothing (void) {
 
226
    ULE_S ule;
 
227
    ule.uxrs = ule.uxrs_static;
 
228
 
 
229
    //Set up defaults.
 
230
    int committed;
 
231
    for (committed = 1; committed < MAX_TRANSACTION_RECORDS; committed++) {
 
232
        int32_t num_xrs;
 
233
 
 
234
        for (num_xrs = committed; num_xrs < MAX_TRANSACTION_RECORDS; num_xrs++) {
 
235
            ule.num_cuxrs = committed;
 
236
            ule.num_puxrs = num_xrs - committed;
 
237
            if (num_xrs == 1) {
 
238
                ule.uxrs[num_xrs-1].xid    = TXNID_NONE;
 
239
            }
 
240
            else {
 
241
                ule.uxrs[num_xrs-1].xid    = ule.uxrs[num_xrs-2].xid + (random() % 32 + 1); //Abitrary number, xids must be strictly increasing
 
242
            }
 
243
            ule.uxrs[num_xrs-1].type = XR_DELETE;
 
244
            test_ule_packs_to_nothing(&ule);
 
245
            if (num_xrs > 2 && num_xrs > committed && num_xrs % 4) {
 
246
                //Set some of them to placeholders instead of deletes
 
247
                ule.uxrs[num_xrs-2].type = XR_PLACEHOLDER;
 
248
            }
 
249
            test_ule_packs_to_nothing(&ule);
 
250
        }
 
251
    }
 
252
 
 
253
}
 
254
 
 
255
static void
 
256
le_verify_accessors(LEAFENTRY le, ULE ule, size_t pre_calculated_memsize) {
 
257
    assert(le);
 
258
    assert(ule->num_cuxrs > 0);
 
259
    assert(ule->num_puxrs <= MAX_TRANSACTION_RECORDS);
 
260
    assert(ule->uxrs[ule->num_cuxrs + ule->num_puxrs-1].type != XR_PLACEHOLDER);
 
261
    //Extract expected values from ULE
 
262
    size_t memsize  = le_memsize_from_ule(ule);
 
263
    size_t num_uxrs = ule->num_cuxrs + ule->num_puxrs;
 
264
 
 
265
    void *latest_val        = ule->uxrs[num_uxrs -1].type == XR_DELETE ? NULL : ule->uxrs[num_uxrs -1].valp;
 
266
    uint32_t latest_vallen = ule->uxrs[num_uxrs -1].type == XR_DELETE ? 0    : ule->uxrs[num_uxrs -1].vallen;
 
267
    {
 
268
        int i;
 
269
        for (i = num_uxrs - 1; i >= 0; i--) {
 
270
            if (ule->uxrs[i].type == XR_INSERT) {
 
271
                goto found_insert;
 
272
            }
 
273
        }
 
274
        assert(false);
 
275
    }
 
276
found_insert:;
 
277
    TXNID outermost_uncommitted_xid = ule->num_puxrs == 0 ? TXNID_NONE : ule->uxrs[ule->num_cuxrs].xid;
 
278
    int   is_provdel = ule->uxrs[num_uxrs-1].type == XR_DELETE;
 
279
 
 
280
    assert(le!=NULL);
 
281
    //Verify all accessors
 
282
    assert(memsize  == pre_calculated_memsize);
 
283
    assert(memsize  == leafentry_memsize(le));
 
284
    {
 
285
        uint32_t test_vallen;
 
286
        void*     test_valp = le_latest_val_and_len(le, &test_vallen);
 
287
        if (latest_val != NULL) assert(test_valp != latest_val);
 
288
        assert(test_vallen == latest_vallen);
 
289
        assert(memcmp(test_valp, latest_val, test_vallen) == 0);
 
290
        assert(le_latest_val(le)    == test_valp);
 
291
        assert(le_latest_vallen(le) == test_vallen);
 
292
    }
 
293
    {
 
294
        assert(le_outermost_uncommitted_xid(le) == outermost_uncommitted_xid);
 
295
    }
 
296
    {
 
297
        assert((le_latest_is_del(le)==0) == (is_provdel==0));
 
298
    }
 
299
}
 
300
 
 
301
 
 
302
 
 
303
static void
 
304
test_le_pack_committed (void) {
 
305
    ULE_S ule;
 
306
    ule.uxrs = ule.uxrs_static;
 
307
 
 
308
    uint8_t val[MAX_SIZE];
 
309
    uint32_t valsize;
 
310
    for (valsize = 0; valsize < MAX_SIZE; valsize += (random() % MAX_SIZE) + 1) {
 
311
        fillrandom(val, valsize);
 
312
 
 
313
        ule.num_cuxrs       = 1;
 
314
        ule.num_puxrs       = 0;
 
315
        ule.uxrs[0].type   = XR_INSERT;
 
316
        ule.uxrs[0].xid    = 0;
 
317
        ule.uxrs[0].valp   = val;
 
318
        ule.uxrs[0].vallen = valsize;
 
319
 
 
320
        size_t memsize;
 
321
        LEAFENTRY le;
 
322
        int r = le_pack(&ule, nullptr, 0, nullptr, 0, 0, &le);
 
323
        assert(r==0);
 
324
        assert(le!=NULL);
 
325
        memsize = le_memsize_from_ule(&ule);
 
326
        le_verify_accessors(le, &ule, memsize);
 
327
        ULE_S tmp_ule;
 
328
        le_unpack(&tmp_ule, le);
 
329
        verify_ule_equal(&ule, &tmp_ule);
 
330
        LEAFENTRY tmp_le;
 
331
        size_t    tmp_memsize;
 
332
        r = le_pack(&tmp_ule, nullptr, 0, nullptr, 0, 0, &tmp_le);
 
333
        tmp_memsize = le_memsize_from_ule(&tmp_ule);
 
334
        assert(r==0);
 
335
        assert(tmp_memsize == memsize);
 
336
        assert(memcmp(le, tmp_le, memsize) == 0);
 
337
        le_verify_accessors(tmp_le, &tmp_ule, tmp_memsize);
 
338
 
 
339
        toku_free(tmp_le);
 
340
        toku_free(le);
 
341
        ule_cleanup(&tmp_ule);
 
342
    }
 
343
}
 
344
 
 
345
static void
 
346
test_le_pack_uncommitted (uint8_t committed_type, uint8_t prov_type, int num_placeholders) {
 
347
    ULE_S ule;
 
348
    ule.uxrs = ule.uxrs_static;
 
349
    assert(num_placeholders >= 0);
 
350
 
 
351
    uint8_t cval[MAX_SIZE];
 
352
    uint8_t pval[MAX_SIZE];
 
353
    uint32_t cvalsize;
 
354
    uint32_t pvalsize;
 
355
    for (cvalsize = 0; cvalsize < MAX_SIZE; cvalsize += (random() % MAX_SIZE) + 1) {
 
356
        pvalsize = (cvalsize + random()) % MAX_SIZE;
 
357
        if (committed_type == XR_INSERT)
 
358
            fillrandom(cval, cvalsize);
 
359
        if (prov_type == XR_INSERT)
 
360
            fillrandom(pval, pvalsize);
 
361
        ule.uxrs[0].type   = committed_type;
 
362
        ule.uxrs[0].xid    = TXNID_NONE;
 
363
        ule.uxrs[0].vallen = cvalsize;
 
364
        ule.uxrs[0].valp   = cval;
 
365
        ule.num_cuxrs       = 1;
 
366
        ule.num_puxrs       = 1 + num_placeholders;
 
367
 
 
368
        uint32_t idx;
 
369
        for (idx = 1; idx <= (uint32_t)num_placeholders; idx++) {
 
370
            ule.uxrs[idx].type = XR_PLACEHOLDER;
 
371
            ule.uxrs[idx].xid  = ule.uxrs[idx-1].xid + (random() % 32 + 1); //Abitrary number, xids must be strictly increasing
 
372
        }
 
373
        ule.uxrs[idx].xid  = ule.uxrs[idx-1].xid + (random() % 32 + 1); //Abitrary number, xids must be strictly increasing
 
374
        ule.uxrs[idx].type   = prov_type;
 
375
        ule.uxrs[idx].vallen = pvalsize;
 
376
        ule.uxrs[idx].valp   = pval;
 
377
 
 
378
        size_t memsize;
 
379
        LEAFENTRY le;
 
380
        int r = le_pack(&ule, nullptr, 0, nullptr, 0, 0, &le);
 
381
        assert(r==0);
 
382
        assert(le!=NULL);
 
383
        memsize = le_memsize_from_ule(&ule);
 
384
        le_verify_accessors(le, &ule, memsize);
 
385
        ULE_S tmp_ule;
 
386
        le_unpack(&tmp_ule, le);
 
387
        verify_ule_equal(&ule, &tmp_ule);
 
388
        LEAFENTRY tmp_le;
 
389
        size_t    tmp_memsize;
 
390
        r = le_pack(&tmp_ule, nullptr, 0, nullptr, 0, 0, &tmp_le);
 
391
        tmp_memsize = le_memsize_from_ule(&tmp_ule);
 
392
        assert(r==0);
 
393
        assert(tmp_memsize == memsize);
 
394
        assert(memcmp(le, tmp_le, memsize) == 0);
 
395
        le_verify_accessors(tmp_le, &tmp_ule, tmp_memsize);
 
396
 
 
397
        toku_free(tmp_le);
 
398
        toku_free(le);
 
399
        ule_cleanup(&tmp_ule);
 
400
    }
 
401
}
 
402
 
 
403
static void
 
404
test_le_pack_provpair (int num_placeholders) {
 
405
    test_le_pack_uncommitted(XR_DELETE, XR_INSERT, num_placeholders);
 
406
}
 
407
 
 
408
static void
 
409
test_le_pack_provdel (int num_placeholders) {
 
410
    test_le_pack_uncommitted(XR_INSERT, XR_DELETE, num_placeholders);
 
411
}
 
412
 
 
413
static void
 
414
test_le_pack_both (int num_placeholders) {
 
415
    test_le_pack_uncommitted(XR_INSERT, XR_INSERT, num_placeholders);
 
416
}
 
417
 
 
418
//Test of PACK
 
419
//  Committed leafentry
 
420
//      delete -> nothing (le_empty_packs_to_nothing)
 
421
//      insert
 
422
//          make key/val have diff lengths/content
 
423
//  Uncommitted
 
424
//      committed delete
 
425
//          followed by placeholder*, delete (le_empty_packs_to_nothing)
 
426
//          followed by placeholder*, insert
 
427
//      committed insert
 
428
//          followed by placeholder*, delete
 
429
//          followed by placeholder*, insert
 
430
//          
 
431
//  placeholder* is 0,1, or 2 placeholders
 
432
static void
 
433
test_le_pack (void) {
 
434
    test_le_empty_packs_to_nothing();
 
435
    test_le_pack_committed();
 
436
    int i;
 
437
    for (i = 0; i < 3; i++) {
 
438
        test_le_pack_provpair(i);
 
439
        test_le_pack_provdel(i);
 
440
        test_le_pack_both(i);
 
441
    }
 
442
}
 
443
 
 
444
static void
 
445
test_le_apply(ULE ule_initial, FT_MSG msg, ULE ule_expected) {
 
446
    int r;
 
447
    LEAFENTRY le_initial;
 
448
    LEAFENTRY le_expected;
 
449
    LEAFENTRY le_result;
 
450
 
 
451
    r = le_pack(ule_initial, nullptr, 0, nullptr, 0, 0, &le_initial);
 
452
    CKERR(r);
 
453
 
 
454
    size_t result_memsize = 0;
 
455
    int64_t ignoreme;
 
456
    toku_le_apply_msg(msg,
 
457
                      le_initial,
 
458
                      nullptr,
 
459
                      0,
 
460
                      TXNID_NONE,
 
461
                      make_gc_info(true),
 
462
                      &le_result,
 
463
                      &ignoreme);
 
464
    if (le_result) {
 
465
        result_memsize = leafentry_memsize(le_result);
 
466
        le_verify_accessors(le_result, ule_expected, result_memsize);
 
467
    }
 
468
 
 
469
    size_t expected_memsize = 0;
 
470
    r = le_pack(ule_expected, nullptr, 0, nullptr, 0, 0, &le_expected);
 
471
    CKERR(r);
 
472
    if (le_expected) {
 
473
        expected_memsize = leafentry_memsize(le_expected);
 
474
    }
 
475
 
 
476
 
 
477
    verify_le_equal(le_result, le_expected);
 
478
    if (le_result && le_expected) {
 
479
        assert(result_memsize  == expected_memsize);
 
480
    }
 
481
    if (le_initial)  toku_free(le_initial);
 
482
    if (le_result)   toku_free(le_result);
 
483
    if (le_expected) toku_free(le_expected);
 
484
}
 
485
 
 
486
static const ULE_S ule_committed_delete = {
 
487
    .num_puxrs = 0,
 
488
    .num_cuxrs = 1,
 
489
    .uxrs_static = {{
 
490
        .type   = XR_DELETE,
 
491
        .vallen = 0,
 
492
        .valp   = NULL,
 
493
        .xid    = 0
 
494
    }},
 
495
    .uxrs = (UXR_S *)ule_committed_delete.uxrs_static
 
496
};
 
497
 
 
498
static FT_MSG_S
 
499
msg_init(enum ft_msg_type type, XIDS xids,
 
500
         DBT *key, DBT *val) {
 
501
    FT_MSG_S msg;
 
502
    msg.type = type;
 
503
    msg.xids = xids;
 
504
    msg.u.id.key = key;
 
505
    msg.u.id.val = val;
 
506
    return msg;
 
507
}
 
508
 
 
509
static uint32_t
 
510
next_nesting_level(uint32_t current) {
 
511
    uint32_t rval = current + 1;
 
512
 
 
513
    if (current > 3 && current < MAX_TRANSACTION_RECORDS - 1) {
 
514
        rval = current + random() % 100;
 
515
        if (rval >= MAX_TRANSACTION_RECORDS)
 
516
            rval = MAX_TRANSACTION_RECORDS - 1;
 
517
    }
 
518
    return rval;
 
519
}
 
520
 
 
521
static void
 
522
generate_committed_for(ULE ule, DBT *val) {
 
523
    ule->num_cuxrs = 1;
 
524
    ule->num_puxrs = 0;
 
525
    ule->uxrs = ule->uxrs_static;
 
526
    ule->uxrs[0].type   = XR_INSERT;
 
527
    ule->uxrs[0].vallen = val->size;
 
528
    ule->uxrs[0].valp   = val->data;
 
529
    ule->uxrs[0].xid    = 0;
 
530
}
 
531
 
 
532
static void
 
533
generate_provpair_for(ULE ule, FT_MSG msg) {
 
534
    uint32_t level;
 
535
    XIDS xids = msg->xids;
 
536
    ule->uxrs = ule->uxrs_static;
 
537
 
 
538
    ule->num_cuxrs = 1;
 
539
    ule->num_puxrs = xids_get_num_xids(xids);
 
540
    uint32_t num_uxrs = ule->num_cuxrs + ule->num_puxrs;
 
541
    ule->uxrs[0].type   = XR_DELETE;
 
542
    ule->uxrs[0].vallen = 0;
 
543
    ule->uxrs[0].valp   = NULL;
 
544
    ule->uxrs[0].xid    = TXNID_NONE;
 
545
    for (level = 1; level < num_uxrs - 1; level++) {
 
546
        ule->uxrs[level].type   = XR_PLACEHOLDER;
 
547
        ule->uxrs[level].vallen = 0;
 
548
        ule->uxrs[level].valp   = NULL;
 
549
        ule->uxrs[level].xid    = xids_get_xid(xids, level-1);
 
550
    }
 
551
    ule->uxrs[num_uxrs - 1].type   = XR_INSERT;
 
552
    ule->uxrs[num_uxrs - 1].vallen = msg->u.id.val->size;
 
553
    ule->uxrs[num_uxrs - 1].valp   = msg->u.id.val->data;
 
554
    ule->uxrs[num_uxrs - 1].xid    = xids_get_innermost_xid(xids);
 
555
}
 
556
 
 
557
//Test all the different things that can happen to a
 
558
//non-existent leafentry (logical equivalent of a committed delete).
 
559
static void
 
560
test_le_empty_apply(void) {
 
561
    ULE_S ule_initial        = ule_committed_delete;
 
562
    FT_MSG_S msg;
 
563
 
 
564
    DBT key;
 
565
    DBT val;
 
566
    uint8_t keybuf[MAX_SIZE];
 
567
    uint8_t valbuf[MAX_SIZE];
 
568
    uint32_t keysize;
 
569
    uint32_t valsize;
 
570
    uint32_t  nesting_level;
 
571
    for (keysize = 0; keysize < MAX_SIZE; keysize += (random() % MAX_SIZE) + 1) {
 
572
        for (valsize = 0; valsize < MAX_SIZE; valsize += (random() % MAX_SIZE) + 1) {
 
573
            for (nesting_level = 0;
 
574
                 nesting_level < MAX_TRANSACTION_RECORDS;
 
575
                 nesting_level = next_nesting_level(nesting_level)) {
 
576
                XIDS msg_xids = nested_xids[nesting_level];
 
577
                fillrandom(keybuf, keysize);
 
578
                fillrandom(valbuf, valsize);
 
579
                toku_fill_dbt(&key, keybuf, keysize);
 
580
                toku_fill_dbt(&val, valbuf, valsize);
 
581
 
 
582
                //COMMIT/ABORT is illegal with TXNID 0
 
583
                if (nesting_level > 0) {
 
584
                    //Abort/commit of an empty le is an empty le
 
585
                    ULE_S ule_expected = ule_committed_delete;
 
586
 
 
587
                    msg = msg_init(FT_COMMIT_ANY, msg_xids,  &key, &val);
 
588
                    test_le_apply(&ule_initial, &msg, &ule_expected);
 
589
                    msg = msg_init(FT_COMMIT_BROADCAST_TXN, msg_xids,  &key, &val);
 
590
                    test_le_apply(&ule_initial, &msg, &ule_expected);
 
591
 
 
592
                    msg = msg_init(FT_ABORT_ANY, msg_xids, &key, &val);
 
593
                    test_le_apply(&ule_initial, &msg, &ule_expected);
 
594
                    msg = msg_init(FT_ABORT_BROADCAST_TXN, msg_xids, &key, &val);
 
595
                    test_le_apply(&ule_initial, &msg, &ule_expected);
 
596
                }
 
597
                {
 
598
                    //delete of an empty le is an empty le
 
599
                    ULE_S ule_expected = ule_committed_delete;
 
600
 
 
601
                    msg = msg_init(FT_DELETE_ANY, msg_xids, &key, &val);
 
602
                    test_le_apply(&ule_initial, &msg, &ule_expected);
 
603
                }
 
604
                {
 
605
                    msg = msg_init(FT_INSERT, msg_xids, &key, &val);
 
606
                    ULE_S ule_expected;
 
607
                    generate_provpair_for(&ule_expected, &msg);
 
608
                    test_le_apply(&ule_initial, &msg, &ule_expected);
 
609
                }
 
610
                {
 
611
                    msg = msg_init(FT_INSERT_NO_OVERWRITE, msg_xids, &key, &val);
 
612
                    ULE_S ule_expected;
 
613
                    generate_provpair_for(&ule_expected, &msg);
 
614
                    test_le_apply(&ule_initial, &msg, &ule_expected);
 
615
                }
 
616
            }
 
617
        }
 
618
    }
 
619
}
 
620
 
 
621
static void
 
622
generate_provdel_for(ULE ule, FT_MSG msg) {
 
623
    uint32_t level;
 
624
    XIDS xids = msg->xids;
 
625
 
 
626
    ule->num_cuxrs = 1;
 
627
    ule->num_puxrs = xids_get_num_xids(xids);
 
628
    uint32_t num_uxrs = ule->num_cuxrs + ule->num_puxrs;
 
629
    ule->uxrs[0].type   = XR_INSERT;
 
630
    ule->uxrs[0].vallen = msg->u.id.val->size;
 
631
    ule->uxrs[0].valp   = msg->u.id.val->data;
 
632
    ule->uxrs[0].xid    = TXNID_NONE;
 
633
    for (level = ule->num_cuxrs; level < ule->num_cuxrs + ule->num_puxrs - 1; level++) {
 
634
        ule->uxrs[level].type   = XR_PLACEHOLDER;
 
635
        ule->uxrs[level].vallen = 0;
 
636
        ule->uxrs[level].valp   = NULL;
 
637
        ule->uxrs[level].xid    = xids_get_xid(xids, level-1);
 
638
    }
 
639
    ule->uxrs[num_uxrs - 1].type   = XR_DELETE;
 
640
    ule->uxrs[num_uxrs - 1].vallen = 0;
 
641
    ule->uxrs[num_uxrs - 1].valp   = NULL;
 
642
    ule->uxrs[num_uxrs - 1].xid    = xids_get_innermost_xid(xids);
 
643
}
 
644
 
 
645
static void
 
646
generate_both_for(ULE ule, DBT *oldval, FT_MSG msg) {
 
647
    uint32_t level;
 
648
    XIDS xids = msg->xids;
 
649
 
 
650
    ule->num_cuxrs = 1;
 
651
    ule->num_puxrs = xids_get_num_xids(xids);
 
652
    uint32_t num_uxrs = ule->num_cuxrs + ule->num_puxrs;
 
653
    ule->uxrs[0].type   = XR_INSERT;
 
654
    ule->uxrs[0].vallen = oldval->size;
 
655
    ule->uxrs[0].valp   = oldval->data;
 
656
    ule->uxrs[0].xid    = TXNID_NONE;
 
657
    for (level = ule->num_cuxrs; level < ule->num_cuxrs + ule->num_puxrs - 1; level++) {
 
658
        ule->uxrs[level].type   = XR_PLACEHOLDER;
 
659
        ule->uxrs[level].vallen = 0;
 
660
        ule->uxrs[level].valp   = NULL;
 
661
        ule->uxrs[level].xid    = xids_get_xid(xids, level-1);
 
662
    }
 
663
    ule->uxrs[num_uxrs - 1].type   = XR_INSERT;
 
664
    ule->uxrs[num_uxrs - 1].vallen = msg->u.id.val->size;
 
665
    ule->uxrs[num_uxrs - 1].valp   = msg->u.id.val->data;
 
666
    ule->uxrs[num_uxrs - 1].xid    = xids_get_innermost_xid(xids);
 
667
}
 
668
 
 
669
//Test all the different things that can happen to a
 
670
//committed leafentry (logical equivalent of a committed insert).
 
671
static void
 
672
test_le_committed_apply(void) {
 
673
    ULE_S ule_initial;
 
674
    ule_initial.uxrs = ule_initial.uxrs_static;
 
675
    FT_MSG_S msg;
 
676
 
 
677
    DBT key;
 
678
    DBT val;
 
679
    uint8_t valbuf[MAX_SIZE];
 
680
    uint32_t valsize;
 
681
    uint32_t  nesting_level;
 
682
    for (valsize = 0; valsize < MAX_SIZE; valsize += (random() % MAX_SIZE) + 1) {
 
683
        for (nesting_level = 0;
 
684
             nesting_level < MAX_TRANSACTION_RECORDS;
 
685
             nesting_level = next_nesting_level(nesting_level)) {
 
686
            XIDS msg_xids = nested_xids[nesting_level];
 
687
            fillrandom(valbuf, valsize);
 
688
            toku_fill_dbt(&val, valbuf, valsize);
 
689
 
 
690
            //Generate initial ule
 
691
            generate_committed_for(&ule_initial, &val);
 
692
 
 
693
 
 
694
            //COMMIT/ABORT is illegal with TXNID 0
 
695
            if (nesting_level > 0) {
 
696
                //Commit/abort will not change a committed le
 
697
                ULE_S ule_expected = ule_initial;
 
698
                msg = msg_init(FT_COMMIT_ANY, msg_xids,  &key, &val);
 
699
                test_le_apply(&ule_initial, &msg, &ule_expected);
 
700
                msg = msg_init(FT_COMMIT_BROADCAST_TXN, msg_xids,  &key, &val);
 
701
                test_le_apply(&ule_initial, &msg, &ule_expected);
 
702
 
 
703
                msg = msg_init(FT_ABORT_ANY, msg_xids, &key, &val);
 
704
                test_le_apply(&ule_initial, &msg, &ule_expected);
 
705
                msg = msg_init(FT_ABORT_BROADCAST_TXN, msg_xids, &key, &val);
 
706
                test_le_apply(&ule_initial, &msg, &ule_expected);
 
707
            }
 
708
 
 
709
            {
 
710
                msg = msg_init(FT_DELETE_ANY, msg_xids, &key, &val);
 
711
                ULE_S ule_expected;
 
712
                ule_expected.uxrs = ule_expected.uxrs_static;
 
713
                generate_provdel_for(&ule_expected, &msg);
 
714
                test_le_apply(&ule_initial, &msg, &ule_expected);
 
715
            }
 
716
 
 
717
            {
 
718
                uint8_t valbuf2[MAX_SIZE];
 
719
                uint32_t valsize2 = random() % MAX_SIZE;
 
720
                fillrandom(valbuf2, valsize2);
 
721
                DBT val2;
 
722
                toku_fill_dbt(&val2, valbuf2, valsize2);
 
723
                msg = msg_init(FT_INSERT, msg_xids, &key, &val2);
 
724
                ULE_S ule_expected;
 
725
                ule_expected.uxrs = ule_expected.uxrs_static;
 
726
                generate_both_for(&ule_expected, &val, &msg);
 
727
                test_le_apply(&ule_initial, &msg, &ule_expected);
 
728
            }
 
729
            {
 
730
                //INSERT_NO_OVERWRITE will not change a committed insert
 
731
                ULE_S ule_expected = ule_initial;
 
732
                uint8_t valbuf2[MAX_SIZE];
 
733
                uint32_t valsize2 = random() % MAX_SIZE;
 
734
                fillrandom(valbuf2, valsize2);
 
735
                DBT val2;
 
736
                toku_fill_dbt(&val2, valbuf2, valsize2);
 
737
                msg = msg_init(FT_INSERT_NO_OVERWRITE, msg_xids, &key, &val2);
 
738
                test_le_apply(&ule_initial, &msg, &ule_expected);
 
739
            }
 
740
        }
 
741
    }
 
742
}
 
743
 
 
744
static void
 
745
test_le_apply_messages(void) {
 
746
    test_le_empty_apply();
 
747
    test_le_committed_apply();
 
748
}
 
749
 
 
750
static bool ule_worth_running_garbage_collection(ULE ule, TXNID oldest_referenced_xid_known) {
 
751
    LEAFENTRY le;
 
752
    int r = le_pack(ule, nullptr, 0, nullptr, 0, 0, &le); CKERR(r);
 
753
    invariant_notnull(le);
 
754
    bool worth_running = toku_le_worth_running_garbage_collection(le, oldest_referenced_xid_known);
 
755
    toku_free(le);
 
756
    return worth_running;
 
757
}
 
758
 
 
759
static void test_le_garbage_collection_birdie(void) {
 
760
    DBT key;
 
761
    DBT val;
 
762
    ULE_S ule;
 
763
    uint8_t keybuf[MAX_SIZE];
 
764
    uint32_t keysize=8;
 
765
    uint8_t valbuf[MAX_SIZE];
 
766
    uint32_t valsize=8;
 
767
    bool do_garbage_collect;
 
768
 
 
769
    memset(&key, 0, sizeof(key));
 
770
    memset(&val, 0, sizeof(val));
 
771
    fillrandom(keybuf, keysize);
 
772
    fillrandom(valbuf, valsize);
 
773
    memset(&ule, 0, sizeof(ule));
 
774
    ule.uxrs = ule.uxrs_static;
 
775
 
 
776
    //
 
777
    // Test garbage collection "worth-doing" heurstic
 
778
    //
 
779
 
 
780
    // Garbage collection should not be worth doing on a clean leafentry.
 
781
    ule.num_cuxrs = 1;
 
782
    ule.num_puxrs = 0;
 
783
    ule.uxrs[0].xid = TXNID_NONE;
 
784
    ule.uxrs[0].type = XR_INSERT;
 
785
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
786
    invariant(!do_garbage_collect);
 
787
    
 
788
    // It is worth doing when there is more than one committed entry
 
789
    ule.num_cuxrs = 2;
 
790
    ule.num_puxrs = 1;
 
791
    ule.uxrs[1].xid = 500;
 
792
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
793
    invariant(do_garbage_collect);
 
794
    
 
795
    // It is not worth doing when there is one of each, when the
 
796
    // provisional entry is newer than the oldest known referenced xid
 
797
    ule.num_cuxrs = 1;
 
798
    ule.num_puxrs = 1;
 
799
    ule.uxrs[1].xid = 1500;
 
800
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
801
    invariant(!do_garbage_collect);
 
802
    ule.uxrs[1].xid = 200;
 
803
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
804
    invariant(!do_garbage_collect);
 
805
 
 
806
    // It is not worth doing when there is only one committed entry,
 
807
    // multiple provisional entries, but the outermost entry is newer.
 
808
    ule.num_cuxrs = 1;
 
809
    ule.num_puxrs = 3;
 
810
    ule.uxrs[1].xid = 201;
 
811
    ule.uxrs[2].xid = 206;
 
812
    ule.uxrs[3].xid = 215;
 
813
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
814
    invariant(!do_garbage_collect);
 
815
 
 
816
    // It is worth doing when the above scenario has an outermost entry
 
817
    // older than the oldest known, even if its children seem newer.
 
818
    // this children must have commit because the parent is not live.
 
819
    ule.num_cuxrs = 1;
 
820
    ule.num_puxrs = 3;
 
821
    ule.uxrs[1].xid = 190;
 
822
    ule.uxrs[2].xid = 206;
 
823
    ule.uxrs[3].xid = 215;
 
824
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
825
    invariant(do_garbage_collect);
 
826
 
 
827
    // It is worth doing when there is more than one committed entry,
 
828
    // even if a provisional entry exists that is newer than the
 
829
    // oldest known refrenced xid
 
830
    ule.num_cuxrs = 2;
 
831
    ule.num_puxrs = 1;
 
832
    ule.uxrs[1].xid = 499;
 
833
    ule.uxrs[2].xid = 500;
 
834
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
835
    invariant(do_garbage_collect);
 
836
 
 
837
    // It is worth doing when there is one of each, and the provisional
 
838
    // entry is older than the oldest known referenced xid
 
839
    ule.num_cuxrs = 1;
 
840
    ule.num_puxrs = 1;
 
841
    ule.uxrs[1].xid = 199;
 
842
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
843
    invariant(do_garbage_collect);
 
844
 
 
845
    // It is definately worth doing when the above case is true
 
846
    // and there is more than one provisional entry.
 
847
    ule.num_cuxrs = 1;
 
848
    ule.num_puxrs = 2;
 
849
    ule.uxrs[1].xid = 150;
 
850
    ule.uxrs[2].xid = 175;
 
851
    do_garbage_collect = ule_worth_running_garbage_collection(&ule, 200);
 
852
    invariant(do_garbage_collect);
 
853
}
 
854
 
 
855
static void test_le_optimize(void) {
 
856
    FT_MSG_S msg;
 
857
    DBT key;
 
858
    DBT val;
 
859
    ULE_S ule_initial;
 
860
    ULE_S ule_expected;
 
861
    uint8_t keybuf[MAX_SIZE];
 
862
    uint32_t keysize=8;
 
863
    uint8_t valbuf[MAX_SIZE];
 
864
    uint32_t valsize=8;
 
865
    ule_initial.uxrs = ule_initial.uxrs_static;
 
866
    ule_expected.uxrs = ule_expected.uxrs_static;
 
867
    TXNID optimize_txnid = 1000;
 
868
    memset(&key, 0, sizeof(key));
 
869
    memset(&val, 0, sizeof(val));
 
870
    XIDS root_xids = xids_get_root_xids();
 
871
    XIDS msg_xids; 
 
872
    int r = xids_create_child(root_xids, &msg_xids, optimize_txnid);
 
873
    assert(r==0);
 
874
    msg = msg_init(FT_OPTIMIZE, msg_xids, &key, &val);
 
875
 
 
876
    //
 
877
    // create the key
 
878
    //
 
879
    fillrandom(keybuf, keysize);
 
880
    fillrandom(valbuf, valsize);
 
881
 
 
882
    //
 
883
    // test a clean leafentry has no effect
 
884
    //
 
885
    ule_initial.num_cuxrs = 1;
 
886
    ule_initial.num_puxrs = 0;
 
887
    ule_initial.uxrs[0].type = XR_INSERT;
 
888
    ule_initial.uxrs[0].xid = TXNID_NONE;
 
889
    ule_initial.uxrs[0].vallen = valsize;
 
890
    ule_initial.uxrs[0].valp = valbuf;
 
891
    
 
892
    ule_expected.num_cuxrs = 1;
 
893
    ule_expected.num_puxrs = 0;
 
894
    ule_expected.uxrs[0].type = XR_INSERT;
 
895
    ule_expected.uxrs[0].xid = TXNID_NONE;
 
896
    ule_expected.uxrs[0].vallen = valsize;
 
897
    ule_expected.uxrs[0].valp = valbuf;
 
898
 
 
899
    test_msg_modify_ule(&ule_initial,&msg);
 
900
    verify_ule_equal(&ule_initial,&ule_expected);
 
901
 
 
902
    //
 
903
    // add another committed entry and ensure no effect
 
904
    //
 
905
    ule_initial.num_cuxrs = 2;
 
906
    ule_initial.uxrs[1].type = XR_DELETE;
 
907
    ule_initial.uxrs[1].xid = 500;
 
908
    ule_initial.uxrs[1].vallen = 0;
 
909
    ule_initial.uxrs[1].valp = NULL;
 
910
 
 
911
    ule_expected.num_cuxrs = 2;
 
912
    ule_expected.uxrs[1].type = XR_DELETE;
 
913
    ule_expected.uxrs[1].xid = 500;
 
914
    ule_expected.uxrs[1].vallen = 0;
 
915
    ule_expected.uxrs[1].valp = NULL;
 
916
    
 
917
    test_msg_modify_ule(&ule_initial,&msg);
 
918
    verify_ule_equal(&ule_initial,&ule_expected);
 
919
 
 
920
    //
 
921
    // now test when there is one provisional, three cases, after, equal, and before FT_OPTIMIZE's transaction
 
922
    //
 
923
    ule_initial.num_cuxrs = 1;
 
924
    ule_initial.num_puxrs = 1;
 
925
    ule_initial.uxrs[1].xid = 1500;
 
926
 
 
927
    ule_expected.num_cuxrs = 1;
 
928
    ule_expected.num_puxrs = 1;
 
929
    ule_expected.uxrs[1].xid = 1500;
 
930
    test_msg_modify_ule(&ule_initial,&msg);
 
931
    verify_ule_equal(&ule_initial,&ule_expected);
 
932
 
 
933
    ule_initial.uxrs[1].xid = 1000;
 
934
    ule_expected.uxrs[1].xid = 1000;
 
935
    test_msg_modify_ule(&ule_initial,&msg);
 
936
    verify_ule_equal(&ule_initial,&ule_expected);
 
937
 
 
938
    ule_initial.uxrs[1].xid = 500;
 
939
    ule_expected.uxrs[1].xid = 500;
 
940
    ule_expected.num_cuxrs = 2;
 
941
    ule_expected.num_puxrs = 0;
 
942
    test_msg_modify_ule(&ule_initial,&msg);
 
943
    verify_ule_equal(&ule_initial,&ule_expected);
 
944
 
 
945
    //
 
946
    // now test cases with two provisional
 
947
    //
 
948
    ule_initial.num_cuxrs = 1;
 
949
    ule_initial.num_puxrs = 2;
 
950
    ule_expected.num_cuxrs = 1;
 
951
    ule_expected.num_puxrs = 2;
 
952
 
 
953
    ule_initial.uxrs[2].type = XR_INSERT;
 
954
    ule_initial.uxrs[2].xid = 1500;
 
955
    ule_initial.uxrs[2].vallen = valsize;
 
956
    ule_initial.uxrs[2].valp = valbuf;
 
957
    ule_initial.uxrs[1].xid = 1200;
 
958
    
 
959
    ule_expected.uxrs[2].type = XR_INSERT;
 
960
    ule_expected.uxrs[2].xid = 1500;
 
961
    ule_expected.uxrs[2].vallen = valsize;
 
962
    ule_expected.uxrs[2].valp = valbuf;
 
963
    ule_expected.uxrs[1].xid = 1200;
 
964
    test_msg_modify_ule(&ule_initial,&msg);
 
965
    verify_ule_equal(&ule_initial,&ule_expected);
 
966
 
 
967
    ule_initial.uxrs[1].xid = 1000;
 
968
    ule_expected.uxrs[1].xid = 1000;
 
969
    test_msg_modify_ule(&ule_initial,&msg);
 
970
    verify_ule_equal(&ule_initial,&ule_expected);
 
971
 
 
972
    ule_initial.uxrs[1].xid = 800;
 
973
    ule_expected.uxrs[1].xid = 800;
 
974
    ule_expected.num_cuxrs = 2;
 
975
    ule_expected.num_puxrs = 0;
 
976
    ule_expected.uxrs[1].type = ule_initial.uxrs[2].type;
 
977
    ule_expected.uxrs[1].valp = ule_initial.uxrs[2].valp;
 
978
    ule_expected.uxrs[1].vallen = ule_initial.uxrs[2].vallen;
 
979
    test_msg_modify_ule(&ule_initial,&msg);
 
980
    verify_ule_equal(&ule_initial,&ule_expected);
 
981
 
 
982
    
 
983
    xids_destroy(&msg_xids);
 
984
    xids_destroy(&root_xids);
 
985
}
 
986
 
 
987
//TODO: #1125 tests:
 
988
//      Will probably have to expose ULE_S definition
 
989
//            - Check memsize function is correct
 
990
//             - Assert == disksize (almost useless, but go ahead)
 
991
//            - Check standard accessors
 
992
//             - le_latest_val_and_len
 
993
//             - le_latest_val 
 
994
//             - le_latest_vallen
 
995
//             - le_key_and_len
 
996
//             - le_innermost_inserted_val_and_len
 
997
//             - le_innermost_inserted_val 
 
998
//             - le_innermost_inserted_vallen
 
999
//            - Check le_outermost_uncommitted_xid
 
1000
//            - Check le_latest_is_del
 
1001
//            - Check unpack+pack memcmps equal
 
1002
//            - Check exact memory expected (including size) for various leafentry types.
 
1003
//            - Check apply_msg logic
 
1004
//             - Known start, known expected.. various types.
 
1005
//            - Go through test-leafentry10.c
 
1006
//             - Verify we have tests for all analogous stuff.
 
1007
//
 
1008
//  PACK
 
1009
//  UNPACK
 
1010
//      verify pack+unpack is no-op
 
1011
//      verify unpack+pack is no-op
 
1012
//  accessors
 
1013
//  Test apply_msg logic
 
1014
//      i.e. start with LE, apply message
 
1015
//          in parallel, construct the expected ULE manually, and pack that
 
1016
//          Compare the two results
 
1017
//  Test full_promote
 
1018
 
 
1019
static void
 
1020
init_xids(void) {
 
1021
    uint32_t i;
 
1022
    nested_xids[0] = xids_get_root_xids();
 
1023
    for (i = 1; i < MAX_TRANSACTION_RECORDS; i++) {
 
1024
        int r = xids_create_child(nested_xids[i-1], &nested_xids[i], i * 37 + random() % 36);
 
1025
        assert(r==0);
 
1026
    }
 
1027
}
 
1028
 
 
1029
static void
 
1030
destroy_xids(void) {
 
1031
    uint32_t i;
 
1032
    for (i = 0; i < MAX_TRANSACTION_RECORDS; i++) {
 
1033
        xids_destroy(&nested_xids[i]);
 
1034
    }
 
1035
}
 
1036
 
 
1037
int
 
1038
test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
 
1039
    srandom(7); //Arbitrary seed.
 
1040
    init_xids();
 
1041
    test_le_offsets();
 
1042
    test_le_pack();
 
1043
    test_le_apply_messages();
 
1044
    test_le_optimize();
 
1045
    test_le_garbage_collection_birdie();
 
1046
    destroy_xids();
 
1047
    return 0;
 
1048
}
 
1049