• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / jorgen.edelbo_333

01 Jul 2024 07:21AM UTC coverage: 90.865% (-0.08%) from 90.948%
jorgen.edelbo_333

Pull #7826

Evergreen

jedelbo
Merge tag 'v14.10.2' into next-major
Pull Request #7826: Merge Next major

102912 of 181138 branches covered (56.81%)

3131 of 3738 new or added lines in 54 files covered. (83.76%)

80 existing lines in 14 files now uncovered.

217498 of 239364 relevant lines covered (90.86%)

6655796.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.87
/test/test_array.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2016 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#include "testsettings.hpp"
20
#ifdef TEST_ARRAY
21

22
#include <cstdlib>
23
#include <algorithm>
24
#include <string>
25
#include <vector>
26
#include <map>
27

28
#include <realm/array_with_find.hpp>
29
#include <realm/array_unsigned.hpp>
30
#include <realm/column_integer.hpp>
31
#include <realm/query_conditions.hpp>
32
#include <realm/array_direct.hpp>
33

34
#include "test.hpp"
35

36
using namespace realm;
37
using namespace realm::test_util;
38
using unit_test::TestContext;
39

40

41
// Test independence and thread-safety
42
// -----------------------------------
43
//
44
// All tests must be thread safe and independent of each other. This
45
// is required because it allows for both shuffling of the execution
46
// order and for parallelized testing.
47
//
48
// In particular, avoid using std::rand() since it is not guaranteed
49
// to be thread safe. Instead use the API offered in
50
// `test/util/random.hpp`.
51
//
52
// All files created in tests must use the TEST_PATH macro (or one of
53
// its friends) to obtain a suitable file system path. See
54
// `test/util/test_path.hpp`.
55
//
56
//
57
// Debugging and the ONLY() macro
58
// ------------------------------
59
//
60
// A simple way of disabling all tests except one called `Foo`, is to
61
// replace TEST(Foo) with ONLY(Foo) and then recompile and rerun the
62
// test suite. Note that you can also use filtering by setting the
63
// environment varible `UNITTEST_FILTER`. See `README.md` for more on
64
// this.
65
//
66
// Another way to debug a particular test, is to copy that test into
67
// `experiments/testcase.cpp` and then run `sh build.sh
68
// check-testcase` (or one of its friends) from the command line.
69

70

71
namespace {
72

73
void has_zero_byte(TestContext& test_context, int64_t value, size_t reps)
74
{
14✔
75
    Array a(Allocator::get_default());
14✔
76
    a.create(Array::type_Normal);
14✔
77
    IntegerColumn r(Allocator::get_default());
14✔
78
    r.create();
14✔
79

80
    for (size_t i = 0; i < reps - 1; ++i)
1,022✔
81
        a.add(value);
1,008✔
82

83
    a.add(0);
14✔
84

85
    size_t t = a.find_first(0);
14✔
86
    CHECK_EQUAL(a.size() - 1, t);
14✔
87

88
    r.clear();
14✔
89
    ArrayWithFind(a).find_all(&r, 0);
14✔
90
    CHECK_EQUAL(int64_t(a.size() - 1), r.get(0));
14✔
91

92
    // Cleanup
93
    a.destroy();
14✔
94
    r.destroy();
14✔
95
}
14✔
96

97
} // anonymous namespace
98

99
TEST(Array_Bits)
100
{
2✔
101
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(0), 0);
2✔
102
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(1), 1);
2✔
103
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(2), 2);
2✔
104
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(3), 2);
2✔
105
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(4), 3);
2✔
106
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(5), 3);
2✔
107
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(7), 3);
2✔
108
    CHECK_EQUAL(NodeHeader::unsigned_to_num_bits(8), 4);
2✔
109
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(0), 1);
2✔
110
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(1), 2);
2✔
111
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(-1), 1);
2✔
112
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(-2), 2);
2✔
113
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(-3), 3);
2✔
114
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(-4), 3);
2✔
115
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(3), 3);
2✔
116
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(4), 4);
2✔
117
    CHECK_EQUAL(NodeHeader::signed_to_num_bits(7), 4);
2✔
118
}
2✔
119

120
TEST(Array_General)
121
{
2✔
122
    Array c(Allocator::get_default());
2✔
123
    c.create(Array::type_Normal);
2✔
124

125
    // TEST(Array_Add0)
126

127
    c.add(0);
2✔
128
    CHECK_EQUAL(c.get(0), 0);
2✔
129
    CHECK_EQUAL(c.size(), 1);
2✔
130
    CHECK_EQUAL(0, c.get_width());
2✔
131

132

133
    // TEST(Array_Add1)
134

135
    c.add(1);
2✔
136
    CHECK_EQUAL(c.get(0), 0);
2✔
137
    CHECK_EQUAL(c.get(1), 1);
2✔
138
    CHECK_EQUAL(c.size(), 2);
2✔
139
    CHECK_EQUAL(1, c.get_width());
2✔
140

141

142
    // TEST(Array_Add2)
143

144
    c.add(2);
2✔
145
    CHECK_EQUAL(c.get(0), 0);
2✔
146
    CHECK_EQUAL(c.get(1), 1);
2✔
147
    CHECK_EQUAL(c.get(2), 2);
2✔
148
    CHECK_EQUAL(c.size(), 3);
2✔
149
    CHECK_EQUAL(2, c.get_width());
2✔
150

151

152
    // TEST(Array_Add3)
153

154
    c.add(3);
2✔
155
    CHECK_EQUAL(c.get(0), 0);
2✔
156
    CHECK_EQUAL(c.get(1), 1);
2✔
157
    CHECK_EQUAL(c.get(2), 2);
2✔
158
    CHECK_EQUAL(c.get(3), 3);
2✔
159
    CHECK_EQUAL(c.size(), 4);
2✔
160
    CHECK_EQUAL(2, c.get_width());
2✔
161

162

163
    // TEST(Array_Add4)
164

165
    c.add(4);
2✔
166
    CHECK_EQUAL(c.get(0), 0);
2✔
167
    CHECK_EQUAL(c.get(1), 1);
2✔
168
    CHECK_EQUAL(c.get(2), 2);
2✔
169
    CHECK_EQUAL(c.get(3), 3);
2✔
170
    CHECK_EQUAL(c.get(4), 4);
2✔
171
    CHECK_EQUAL(c.size(), 5);
2✔
172
    CHECK_EQUAL(4, c.get_width());
2✔
173

174

175
    // TEST(Array_Add5)
176

177
    c.add(16);
2✔
178
    CHECK_EQUAL(c.get(0), 0);
2✔
179
    CHECK_EQUAL(c.get(1), 1);
2✔
180
    CHECK_EQUAL(c.get(2), 2);
2✔
181
    CHECK_EQUAL(c.get(3), 3);
2✔
182
    CHECK_EQUAL(c.get(4), 4);
2✔
183
    CHECK_EQUAL(c.get(5), 16);
2✔
184
    CHECK_EQUAL(c.size(), 6);
2✔
185
    CHECK_EQUAL(8, c.get_width());
2✔
186

187

188
    // TEST(Array_Add6)
189

190
    c.add(256);
2✔
191
    CHECK_EQUAL(c.get(0), 0);
2✔
192
    CHECK_EQUAL(c.get(1), 1);
2✔
193
    CHECK_EQUAL(c.get(2), 2);
2✔
194
    CHECK_EQUAL(c.get(3), 3);
2✔
195
    CHECK_EQUAL(c.get(4), 4);
2✔
196
    CHECK_EQUAL(c.get(5), 16);
2✔
197
    CHECK_EQUAL(c.get(6), 256);
2✔
198
    CHECK_EQUAL(c.size(), 7);
2✔
199
    CHECK_EQUAL(16, c.get_width());
2✔
200

201

202
    // TEST(Array_Add7)
203

204
    c.add(65536);
2✔
205
    CHECK_EQUAL(c.get(0), 0);
2✔
206
    CHECK_EQUAL(c.get(1), 1);
2✔
207
    CHECK_EQUAL(c.get(2), 2);
2✔
208
    CHECK_EQUAL(c.get(3), 3);
2✔
209
    CHECK_EQUAL(c.get(4), 4);
2✔
210
    CHECK_EQUAL(c.get(5), 16);
2✔
211
    CHECK_EQUAL(c.get(6), 256);
2✔
212
    CHECK_EQUAL(c.get(7), 65536);
2✔
213
    CHECK_EQUAL(c.size(), 8);
2✔
214
    CHECK_EQUAL(32, c.get_width());
2✔
215

216

217
    // TEST(Array_Add8)
218

219
    c.add(4294967296LL);
2✔
220
    CHECK_EQUAL(c.get(0), 0);
2✔
221
    CHECK_EQUAL(c.get(1), 1);
2✔
222
    CHECK_EQUAL(c.get(2), 2);
2✔
223
    CHECK_EQUAL(c.get(3), 3);
2✔
224
    CHECK_EQUAL(c.get(4), 4);
2✔
225
    CHECK_EQUAL(c.get(5), 16);
2✔
226
    CHECK_EQUAL(c.get(6), 256);
2✔
227
    CHECK_EQUAL(c.get(7), 65536);
2✔
228
    CHECK_EQUAL(c.get(8), 4294967296LL);
2✔
229
    CHECK_EQUAL(c.size(), 9);
2✔
230
    CHECK_EQUAL(64, c.get_width());
2✔
231

232

233
    // TEST(Array_AddNeg1)
234

235
    c.clear();
2✔
236
    c.add(-1);
2✔
237

238
    CHECK_EQUAL(c.size(), 1);
2✔
239
    CHECK_EQUAL(c.get(0), -1);
2✔
240
    CHECK_EQUAL(8, c.get_width());
2✔
241

242

243
    // TEST(Array_AddNeg2)
244

245
    c.add(-256);
2✔
246

247
    CHECK_EQUAL(c.size(), 2);
2✔
248
    CHECK_EQUAL(c.get(0), -1);
2✔
249
    CHECK_EQUAL(c.get(1), -256);
2✔
250
    CHECK_EQUAL(16, c.get_width());
2✔
251

252

253
    // TEST(Array_AddNeg3)
254

255
    c.add(-65536);
2✔
256

257
    CHECK_EQUAL(c.size(), 3);
2✔
258
    CHECK_EQUAL(c.get(0), -1);
2✔
259
    CHECK_EQUAL(c.get(1), -256);
2✔
260
    CHECK_EQUAL(c.get(2), -65536);
2✔
261
    CHECK_EQUAL(32, c.get_width());
2✔
262

263

264
    // TEST(Array_AddNeg4)
265

266
    c.add(-4294967296LL);
2✔
267

268
    CHECK_EQUAL(c.size(), 4);
2✔
269
    CHECK_EQUAL(c.get(0), -1);
2✔
270
    CHECK_EQUAL(c.get(1), -256);
2✔
271
    CHECK_EQUAL(c.get(2), -65536);
2✔
272
    CHECK_EQUAL(c.get(3), -4294967296LL);
2✔
273
    CHECK_EQUAL(64, c.get_width());
2✔
274

275

276
    // TEST(Array_Set)
277

278
    c.set(0, 3);
2✔
279
    c.set(1, 2);
2✔
280
    c.set(2, 1);
2✔
281
    c.set(3, 0);
2✔
282

283
    CHECK_EQUAL(c.size(), 4);
2✔
284
    CHECK_EQUAL(c.get(0), 3);
2✔
285
    CHECK_EQUAL(c.get(1), 2);
2✔
286
    CHECK_EQUAL(c.get(2), 1);
2✔
287
    CHECK_EQUAL(c.get(3), 0);
2✔
288

289

290
    // TEST(Array_Insert1)
291

292
    // Set up some initial values
293
    c.clear();
2✔
294
    c.add(0);
2✔
295
    c.add(1);
2✔
296
    c.add(2);
2✔
297
    c.add(3);
2✔
298

299
    // Insert in middle
300
    c.insert(2, 16);
2✔
301

302
    CHECK_EQUAL(c.size(), 5);
2✔
303
    CHECK_EQUAL(c.get(0), 0);
2✔
304
    CHECK_EQUAL(c.get(1), 1);
2✔
305
    CHECK_EQUAL(c.get(2), 16);
2✔
306
    CHECK_EQUAL(c.get(3), 2);
2✔
307
    CHECK_EQUAL(c.get(4), 3);
2✔
308

309

310
    // TEST(Array_Insert2)
311

312
    // Insert at top
313
    c.insert(0, 256);
2✔
314

315
    CHECK_EQUAL(c.size(), 6);
2✔
316
    CHECK_EQUAL(c.get(0), 256);
2✔
317
    CHECK_EQUAL(c.get(1), 0);
2✔
318
    CHECK_EQUAL(c.get(2), 1);
2✔
319
    CHECK_EQUAL(c.get(3), 16);
2✔
320
    CHECK_EQUAL(c.get(4), 2);
2✔
321
    CHECK_EQUAL(c.get(5), 3);
2✔
322

323

324
    // TEST(Array_Insert3)
325

326
    // Insert at bottom
327
    c.insert(6, 65536);
2✔
328

329
    CHECK_EQUAL(c.size(), 7);
2✔
330
    CHECK_EQUAL(c.get(0), 256);
2✔
331
    CHECK_EQUAL(c.get(1), 0);
2✔
332
    CHECK_EQUAL(c.get(2), 1);
2✔
333
    CHECK_EQUAL(c.get(3), 16);
2✔
334
    CHECK_EQUAL(c.get(4), 2);
2✔
335
    CHECK_EQUAL(c.get(5), 3);
2✔
336
    CHECK_EQUAL(c.get(6), 65536);
2✔
337

338

339
    // TEST(Array_Delete1)
340

341
    // Delete from middle
342
    c.erase(3);
2✔
343

344
    CHECK_EQUAL(c.size(), 6);
2✔
345
    CHECK_EQUAL(c.get(0), 256);
2✔
346
    CHECK_EQUAL(c.get(1), 0);
2✔
347
    CHECK_EQUAL(c.get(2), 1);
2✔
348
    CHECK_EQUAL(c.get(3), 2);
2✔
349
    CHECK_EQUAL(c.get(4), 3);
2✔
350
    CHECK_EQUAL(c.get(5), 65536);
2✔
351

352

353
    // TEST(Array_Delete2)
354

355
    // Delete from top
356
    c.erase(0);
2✔
357

358
    CHECK_EQUAL(c.size(), 5);
2✔
359
    CHECK_EQUAL(c.get(0), 0);
2✔
360
    CHECK_EQUAL(c.get(1), 1);
2✔
361
    CHECK_EQUAL(c.get(2), 2);
2✔
362
    CHECK_EQUAL(c.get(3), 3);
2✔
363
    CHECK_EQUAL(c.get(4), 65536);
2✔
364

365

366
    // TEST(Array_Delete3)
367

368
    // Delete from bottom
369
    c.erase(4);
2✔
370

371
    CHECK_EQUAL(c.size(), 4);
2✔
372
    CHECK_EQUAL(c.get(0), 0);
2✔
373
    CHECK_EQUAL(c.get(1), 1);
2✔
374
    CHECK_EQUAL(c.get(2), 2);
2✔
375
    CHECK_EQUAL(c.get(3), 3);
2✔
376

377

378
    // TEST(Array_DeleteAll)
379

380
    // Delete all items one at a time
381
    c.erase(0);
2✔
382
    c.erase(0);
2✔
383
    c.erase(0);
2✔
384
    c.erase(0);
2✔
385

386
    CHECK(c.is_empty());
2✔
387
    CHECK_EQUAL(0, c.size());
2✔
388

389

390
    // TEST(Array_Find1)
391

392
    // Look for a non-existing value
393
    CHECK_EQUAL(size_t(-1), c.find_first(10));
2✔
394

395

396
    // TEST(Array_Find2)
397

398
    // zero-bit width
399
    c.clear();
2✔
400
    c.add(0);
2✔
401
    c.add(0);
2✔
402

403
    CHECK_EQUAL(0, c.find_first(0));
2✔
404

405

406
    // TEST(Array_Find3)
407

408
    // expand to 1-bit width
409
    c.add(1);
2✔
410

411
    CHECK_EQUAL(2, c.find_first(1));
2✔
412

413

414
    // TEST(Array_Find4)
415

416
    // expand to 2-bit width
417
    c.add(2);
2✔
418

419
    CHECK_EQUAL(3, c.find_first(2));
2✔
420

421

422
    // TEST(Array_Find5)
423

424
    // expand to 4-bit width
425
    c.add(4);
2✔
426

427
    CHECK_EQUAL(4, c.find_first(4));
2✔
428

429

430
    // TEST(Array_Find6)
431

432
    // expand to 8-bit width
433
    c.add(16);
2✔
434

435
    // Add some more to make sure we
436
    // can search in 64bit chunks
437
    c.add(16);
2✔
438
    c.add(7);
2✔
439

440
    CHECK_EQUAL(7, c.find_first(7));
2✔
441

442

443
    // TEST(Array_Find7)
444

445
    // expand to 16-bit width
446
    c.add(256);
2✔
447

448
    CHECK_EQUAL(8, c.find_first(256));
2✔
449

450

451
    // TEST(Array_Find8)
452

453
    // expand to 32-bit width
454
    c.add(65536);
2✔
455

456
    CHECK_EQUAL(9, c.find_first(65536));
2✔
457

458

459
    // TEST(Array_Find9)
460

461
    // expand to 64-bit width
462
    c.add(4294967296LL);
2✔
463

464
    CHECK_EQUAL(10, c.find_first(4294967296LL));
2✔
465

466

467
    // Partial find is not fully implemented yet
468
    /*
469
    // TEST(Array_PartialFind1)
470

471
    c.clear();
472

473
    size_t partial_count = 100;
474
    for (size_t i = 0; i != partial_count; ++i)
475
        c.add(i);
476

477
    CHECK_EQUAL(-1, c.find_first(partial_count+1, 0, partial_count));
478
    CHECK_EQUAL(-1, c.find_first(0, 1, partial_count));
479
    CHECK_EQUAL(partial_count-1, c.find_first(partial_count-1, partial_count-1, partial_count));
480
    */
481

482
    // TEST(Array_Destroy)
483

484
    c.destroy();
2✔
485
}
2✔
486

487

488
TEST(Array_Unsigned)
489
{
2✔
490
    ArrayUnsigned c(Allocator::get_default());
2✔
491
    c.create(0, 0);
2✔
492

493
    // TEST(Array_Add0)
494

495
    c.add(0);
2✔
496
    CHECK_EQUAL(c.get(0), 0);
2✔
497
    CHECK_EQUAL(c.size(), 1);
2✔
498
    CHECK_EQUAL(8, c.get_width());
2✔
499

500
    // TEST(Array_Add1)
501

502
    c.add(1);
2✔
503
    CHECK_EQUAL(c.get(0), 0);
2✔
504
    CHECK_EQUAL(c.get(1), 1);
2✔
505
    CHECK_EQUAL(c.size(), 2);
2✔
506
    CHECK_EQUAL(8, c.get_width());
2✔
507

508
    // TEST(Array_Add2)
509

510
    c.add(0xff);
2✔
511
    CHECK_EQUAL(c.get(0), 0);
2✔
512
    CHECK_EQUAL(c.get(1), 1);
2✔
513
    CHECK_EQUAL(c.get(2), 0xff);
2✔
514
    CHECK_EQUAL(c.size(), 3);
2✔
515
    CHECK_EQUAL(8, c.get_width());
2✔
516

517
    // TEST(Array_Add3)
518

519
    c.add(0x100);
2✔
520
    CHECK_EQUAL(c.get(0), 0);
2✔
521
    CHECK_EQUAL(c.get(1), 1);
2✔
522
    CHECK_EQUAL(c.get(2), 0xff);
2✔
523
    CHECK_EQUAL(c.get(3), 0x100);
2✔
524
    CHECK_EQUAL(c.size(), 4);
2✔
525
    CHECK_EQUAL(16, c.get_width());
2✔
526

527
    // TEST(Array_Add4)
528

529
    c.add(0x10000);
2✔
530
    CHECK_EQUAL(c.get(0), 0);
2✔
531
    CHECK_EQUAL(c.get(1), 1);
2✔
532
    CHECK_EQUAL(c.get(2), 0xff);
2✔
533
    CHECK_EQUAL(c.get(3), 0x100);
2✔
534
    CHECK_EQUAL(c.get(4), 0x10000);
2✔
535
    CHECK_EQUAL(c.size(), 5);
2✔
536
    CHECK_EQUAL(32, c.get_width());
2✔
537

538
    // TEST(Array_Insert3)
539

540
    c.insert(3, 0x100000000);
2✔
541
    CHECK_EQUAL(c.get(0), 0);
2✔
542
    CHECK_EQUAL(c.get(1), 1);
2✔
543
    CHECK_EQUAL(c.get(2), 0xff);
2✔
544
    CHECK_EQUAL(c.get(3), 0x100000000);
2✔
545
    CHECK_EQUAL(c.get(4), 0x100);
2✔
546
    CHECK_EQUAL(c.get(5), 0x10000);
2✔
547
    CHECK_EQUAL(c.size(), 6);
2✔
548
    CHECK_EQUAL(64, c.get_width());
2✔
549

550
    // TEST(Array_Insert3)
551

552
    c.insert(5, 7);
2✔
553
    CHECK_EQUAL(c.get(0), 0);
2✔
554
    CHECK_EQUAL(c.get(1), 1);
2✔
555
    CHECK_EQUAL(c.get(2), 0xff);
2✔
556
    CHECK_EQUAL(c.get(3), 0x100000000);
2✔
557
    CHECK_EQUAL(c.get(4), 0x100);
2✔
558
    CHECK_EQUAL(c.get(5), 7);
2✔
559
    CHECK_EQUAL(c.get(6), 0x10000);
2✔
560
    CHECK_EQUAL(c.size(), 7);
2✔
561

562
    c.erase(3);
2✔
563
    CHECK_EQUAL(c.get(0), 0);
2✔
564
    CHECK_EQUAL(c.get(1), 1);
2✔
565
    CHECK_EQUAL(c.get(2), 0xff);
2✔
566
    CHECK_EQUAL(c.get(3), 0x100);
2✔
567
    CHECK_EQUAL(c.get(4), 7);
2✔
568
    CHECK_EQUAL(c.get(5), 0x10000);
2✔
569
    CHECK_EQUAL(c.size(), 6);
2✔
570

571
    c.truncate(0);
2✔
572
    CHECK_EQUAL(c.size(), 0);
2✔
573
    CHECK_EQUAL(8, c.get_width());
2✔
574
    c.add(1);
2✔
575
    c.add(2);
2✔
576
    c.add(2);
2✔
577
    c.add(3);
2✔
578

579
    CHECK_EQUAL(c.lower_bound(1), 0);
2✔
580
    CHECK_EQUAL(c.lower_bound(2), 1);
2✔
581
    CHECK_EQUAL(c.lower_bound(3), 3);
2✔
582

583
    CHECK_EQUAL(c.upper_bound(1), 1);
2✔
584
    CHECK_EQUAL(c.upper_bound(2), 3);
2✔
585
    CHECK_EQUAL(c.upper_bound(3), 4);
2✔
586

587
    c.destroy();
2✔
588
}
2✔
589

590

591
TEST(Array_AddNeg1_1)
592
{
2✔
593
    Array c(Allocator::get_default());
2✔
594
    c.create(Array::type_Normal);
2✔
595

596
    c.add(1);
2✔
597
    c.add(2);
2✔
598
    c.add(3);
2✔
599
    c.add(-128);
2✔
600

601
    CHECK_EQUAL(c.size(), 4);
2✔
602
    CHECK_EQUAL(c.get(0), 1);
2✔
603
    CHECK_EQUAL(c.get(1), 2);
2✔
604
    CHECK_EQUAL(c.get(2), 3);
2✔
605
    CHECK_EQUAL(c.get(3), -128);
2✔
606
    CHECK_EQUAL(8, c.get_width());
2✔
607

608
    c.destroy();
2✔
609
}
2✔
610

611

612
// Oops, see Array_LowerUpperBound
613
TEST(Array_UpperLowerBound)
614
{
2✔
615
    // Tests Array::upper_bound() and Array::lower_bound()
616
    // This test is independent of REALM_MAX_BPNODE_SIZE
617
    Array a(Allocator::get_default());
2✔
618
    a.create(Array::type_Normal);
2✔
619
    std::vector<int> v;
2✔
620
    Random random(random_int<unsigned long>()); // Seed from slow global generator
2✔
621

622
    // we use 4 as constant in order to make border case sequences of
623
    // v, v, v and v, v+1, v+2, etc, probable
624
    for (int i = 0; i < (1000 * (1 + TEST_DURATION * TEST_DURATION * TEST_DURATION * TEST_DURATION * TEST_DURATION));
2,002✔
625
         i++) {
2,000✔
626
        int elements = random.draw_int_mod(64);
2,000✔
627
        int val = random.draw_int_mod(4); // random start value
2,000✔
628

629
        a.clear();
2,000✔
630
        v.clear();
2,000✔
631

632
        for (int e = 0; e < elements; e++) {
66,330✔
633
            a.add(val);
64,330✔
634
            v.push_back(val);
64,330✔
635
            val += random.draw_int_mod(4);
64,330✔
636
        }
64,330✔
637

638
        int64_t searches = val; // val exceeds last value by random.draw_int_mod(4)
2,000✔
639
        for (int64_t s = 0; s < searches; s++) {
101,456✔
640
            size_t uarr = a.upper_bound_int(s);
99,456✔
641
            size_t larr = a.lower_bound_int(s);
99,456✔
642
            size_t uvec = upper_bound(v.begin(), v.end(), s) - v.begin();
99,456✔
643
            size_t lvec = lower_bound(v.begin(), v.end(), s) - v.begin();
99,456✔
644

645
            CHECK_EQUAL(uvec, uarr);
99,456✔
646
            CHECK_EQUAL(lvec, larr);
99,456✔
647
        }
99,456✔
648
    }
2,000✔
649
    a.destroy();
2✔
650
}
2✔
651

652

653
TEST(Array_LowerUpperBound)
654
{
2✔
655
    Array a(Allocator::get_default());
2✔
656
    a.create(Array::type_Normal);
2✔
657

658
    a.add(10);
2✔
659
    a.add(20);
2✔
660
    a.add(30);
2✔
661
    a.add(40);
2✔
662
    a.add(50);
2✔
663
    a.add(60);
2✔
664
    a.add(70);
2✔
665
    a.add(80);
2✔
666

667
    // clang-format off
668
    CHECK_EQUAL(0, a.lower_bound_int(0));  CHECK_EQUAL(0, a.upper_bound_int(0));
2✔
669
    CHECK_EQUAL(0, a.lower_bound_int(1));  CHECK_EQUAL(0, a.upper_bound_int(1));
2✔
670
    CHECK_EQUAL(0, a.lower_bound_int(9));  CHECK_EQUAL(0, a.upper_bound_int(9));
2✔
671
    CHECK_EQUAL(0, a.lower_bound_int(10)); CHECK_EQUAL(1, a.upper_bound_int(10));
2✔
672
    CHECK_EQUAL(1, a.lower_bound_int(11)); CHECK_EQUAL(1, a.upper_bound_int(11));
2✔
673
    CHECK_EQUAL(1, a.lower_bound_int(19)); CHECK_EQUAL(1, a.upper_bound_int(19));
2✔
674
    CHECK_EQUAL(1, a.lower_bound_int(20)); CHECK_EQUAL(2, a.upper_bound_int(20));
2✔
675
    CHECK_EQUAL(2, a.lower_bound_int(21)); CHECK_EQUAL(2, a.upper_bound_int(21));
2✔
676
    CHECK_EQUAL(2, a.lower_bound_int(29)); CHECK_EQUAL(2, a.upper_bound_int(29));
2✔
677
    CHECK_EQUAL(2, a.lower_bound_int(30)); CHECK_EQUAL(3, a.upper_bound_int(30));
2✔
678
    CHECK_EQUAL(3, a.lower_bound_int(31)); CHECK_EQUAL(3, a.upper_bound_int(31));
2✔
679
    CHECK_EQUAL(3, a.lower_bound_int(32)); CHECK_EQUAL(3, a.upper_bound_int(32));
2✔
680
    CHECK_EQUAL(3, a.lower_bound_int(39)); CHECK_EQUAL(3, a.upper_bound_int(39));
2✔
681
    CHECK_EQUAL(3, a.lower_bound_int(40)); CHECK_EQUAL(4, a.upper_bound_int(40));
2✔
682
    CHECK_EQUAL(4, a.lower_bound_int(41)); CHECK_EQUAL(4, a.upper_bound_int(41));
2✔
683
    CHECK_EQUAL(4, a.lower_bound_int(42)); CHECK_EQUAL(4, a.upper_bound_int(42));
2✔
684
    CHECK_EQUAL(4, a.lower_bound_int(49)); CHECK_EQUAL(4, a.upper_bound_int(49));
2✔
685
    CHECK_EQUAL(4, a.lower_bound_int(50)); CHECK_EQUAL(5, a.upper_bound_int(50));
2✔
686
    CHECK_EQUAL(5, a.lower_bound_int(51)); CHECK_EQUAL(5, a.upper_bound_int(51));
2✔
687
    CHECK_EQUAL(5, a.lower_bound_int(52)); CHECK_EQUAL(5, a.upper_bound_int(52));
2✔
688
    CHECK_EQUAL(5, a.lower_bound_int(59)); CHECK_EQUAL(5, a.upper_bound_int(59));
2✔
689
    CHECK_EQUAL(5, a.lower_bound_int(60)); CHECK_EQUAL(6, a.upper_bound_int(60));
2✔
690
    CHECK_EQUAL(6, a.lower_bound_int(61)); CHECK_EQUAL(6, a.upper_bound_int(61));
2✔
691
    CHECK_EQUAL(6, a.lower_bound_int(62)); CHECK_EQUAL(6, a.upper_bound_int(62));
2✔
692
    CHECK_EQUAL(6, a.lower_bound_int(69)); CHECK_EQUAL(6, a.upper_bound_int(69));
2✔
693
    CHECK_EQUAL(6, a.lower_bound_int(70)); CHECK_EQUAL(7, a.upper_bound_int(70));
2✔
694
    CHECK_EQUAL(7, a.lower_bound_int(71)); CHECK_EQUAL(7, a.upper_bound_int(71));
2✔
695
    CHECK_EQUAL(7, a.lower_bound_int(72)); CHECK_EQUAL(7, a.upper_bound_int(72));
2✔
696
    CHECK_EQUAL(7, a.lower_bound_int(78)); CHECK_EQUAL(7, a.upper_bound_int(78));
2✔
697
    CHECK_EQUAL(7, a.lower_bound_int(79)); CHECK_EQUAL(7, a.upper_bound_int(79));
2✔
698
    CHECK_EQUAL(7, a.lower_bound_int(80)); CHECK_EQUAL(8, a.upper_bound_int(80));
2✔
699
    CHECK_EQUAL(8, a.lower_bound_int(81)); CHECK_EQUAL(8, a.upper_bound_int(81));
2✔
700
    CHECK_EQUAL(8, a.lower_bound_int(82)); CHECK_EQUAL(8, a.upper_bound_int(82));
2✔
701
    // clang-format on
702

703
    a.destroy();
2✔
704
}
2✔
705

706

707
/** find_all() int tests spread out over bitwidth
708
 *
709
 */
710

711

712
TEST(Array_FindAllInt0)
713
{
2✔
714
    Array a(Allocator::get_default());
2✔
715
    a.create(Array::type_Normal);
2✔
716
    ArrayWithFind f(a);
2✔
717

718
    IntegerColumn r(Allocator::get_default());
2✔
719
    r.create();
2✔
720

721
    const int value = 0;
2✔
722
    const int vReps = 5;
2✔
723

724
    for (int i = 0; i < vReps; i++) {
12✔
725
        a.add(0);
10✔
726
    }
10✔
727

728
    r.clear();
2✔
729
    f.find_all(&r, 1, 0, 0, 0);
2✔
730
    CHECK_EQUAL(0, r.size());
2✔
731

732
    r.clear();
2✔
733
    f.find_all(&r, 1, 0, vReps - 1, vReps - 1);
2✔
734
    CHECK_EQUAL(0, r.size());
2✔
735

736
    r.clear();
2✔
737
    f.find_all(&r, value);
2✔
738
    CHECK_EQUAL(vReps, r.size());
2✔
739

740
    size_t i = 0;
2✔
741
    size_t j = 0;
2✔
742
    while (i < a.size()) {
12✔
743
        if (a.get(i) == value)
10✔
744
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
745
        i += 1;
10✔
746
    }
10✔
747

748
    // Cleanup
749
    a.destroy();
2✔
750
    r.destroy();
2✔
751
}
2✔
752

753
TEST(Array_FindAllInt1)
754
{
2✔
755
    Array a(Allocator::get_default());
2✔
756
    a.create(Array::type_Normal);
2✔
757
    ArrayWithFind f(a);
2✔
758

759
    IntegerColumn r(Allocator::get_default());
2✔
760
    r.create();
2✔
761

762
    const int value = 1;
2✔
763
    const int vReps = 5;
2✔
764

765
    for (int i = 0; i < vReps; i++) {
12✔
766
        a.add(0);
10✔
767
        a.add(0);
10✔
768
        a.add(1);
10✔
769
        a.add(0);
10✔
770
    }
10✔
771

772
    f.find_all(&r, value);
2✔
773
    CHECK_EQUAL(vReps, r.size());
2✔
774

775
    size_t i = 0;
2✔
776
    size_t j = 0;
2✔
777
    while (i < a.size()) {
42✔
778
        if (a.get(i) == value)
40✔
779
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
780
        i += 1;
40✔
781
    }
40✔
782

783
    // Cleanup
784
    a.destroy();
2✔
785
    r.destroy();
2✔
786
}
2✔
787

788
TEST(Array_FindAllInt2)
789
{
2✔
790
    Array a(Allocator::get_default());
2✔
791
    a.create(Array::type_Normal);
2✔
792
    ArrayWithFind f(a);
2✔
793

794
    IntegerColumn r(Allocator::get_default());
2✔
795
    r.create();
2✔
796

797
    const int value = 3;
2✔
798
    const int vReps = 5;
2✔
799

800
    for (int i = 0; i < vReps; i++) {
12✔
801
        a.add(0);
10✔
802
        a.add(1);
10✔
803
        a.add(2);
10✔
804
        a.add(3);
10✔
805
    }
10✔
806

807
    f.find_all(&r, value);
2✔
808
    CHECK_EQUAL(vReps, r.size());
2✔
809

810
    size_t i = 0;
2✔
811
    size_t j = 0;
2✔
812
    while (i < a.size()) {
42✔
813
        if (a.get(i) == value)
40✔
814
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
815
        i += 1;
40✔
816
    }
40✔
817

818
    // Cleanup
819
    a.destroy();
2✔
820
    r.destroy();
2✔
821
}
2✔
822

823
TEST(Array_FindAllInt3)
824
{
2✔
825
    Array a(Allocator::get_default());
2✔
826
    a.create(Array::type_Normal);
2✔
827
    ArrayWithFind f(a);
2✔
828

829
    IntegerColumn r(Allocator::get_default());
2✔
830
    r.create();
2✔
831

832
    const int value = 10;
2✔
833
    const int vReps = 5;
2✔
834
    // 0, 4, 8
835
    for (int i = 0; i < vReps; i++) {
12✔
836
        a.add(10);
10✔
837
        a.add(11);
10✔
838
        a.add(12);
10✔
839
        a.add(13);
10✔
840
    }
10✔
841

842
    f.find_all(&r, value);
2✔
843
    CHECK_EQUAL(vReps, r.size());
2✔
844

845
    size_t i = 0;
2✔
846
    size_t j = 0;
2✔
847
    while (i < a.size()) {
42✔
848
        if (a.get(i) == value)
40✔
849
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
850
        i += 1;
40✔
851
    }
40✔
852

853
    // Cleanup
854
    a.destroy();
2✔
855
    r.destroy();
2✔
856
}
2✔
857

858
TEST(Array_FindAllInt4)
859
{
2✔
860
    Array a(Allocator::get_default());
2✔
861
    a.create(Array::type_Normal);
2✔
862
    ArrayWithFind f(a);
2✔
863

864
    IntegerColumn r(Allocator::get_default());
2✔
865
    r.create();
2✔
866

867
    const int value = 20;
2✔
868
    const int vReps = 5;
2✔
869

870
    for (int i = 0; i < vReps; i++) {
12✔
871
        // 8 bitwidth
872
        a.add(20);
10✔
873
        a.add(21);
10✔
874
        a.add(22);
10✔
875
        a.add(23);
10✔
876
    }
10✔
877

878
    f.find_all(&r, value);
2✔
879
    CHECK_EQUAL(vReps, r.size());
2✔
880

881
    size_t i = 0;
2✔
882
    size_t j = 0;
2✔
883
    while (i < a.size()) {
42✔
884
        if (a.get(i) == value)
40✔
885
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
886
        i += 1;
40✔
887
    }
40✔
888

889
    // Cleanup
890
    a.destroy();
2✔
891
    r.destroy();
2✔
892
}
2✔
893

894
TEST(Array_FindAllInt5)
895
{
2✔
896
    Array a(Allocator::get_default());
2✔
897
    a.create(Array::type_Normal);
2✔
898
    ArrayWithFind f(a);
2✔
899

900
    IntegerColumn r(Allocator::get_default());
2✔
901
    r.create();
2✔
902

903
    const int value = 303;
2✔
904
    const int vReps = 5;
2✔
905

906
    for (int i = 0; i < vReps; i++) {
12✔
907
        // 16 bitwidth
908
        a.add(300);
10✔
909
        a.add(301);
10✔
910
        a.add(302);
10✔
911
        a.add(303);
10✔
912
    }
10✔
913

914
    f.find_all(&r, value);
2✔
915
    CHECK_EQUAL(vReps, r.size());
2✔
916

917
    size_t i = 0;
2✔
918
    size_t j = 0;
2✔
919
    while (i < a.size()) {
42✔
920
        if (a.get(i) == value)
40✔
921
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
922
        i += 1;
40✔
923
    }
40✔
924

925
    // Cleanup
926
    a.destroy();
2✔
927
    r.destroy();
2✔
928
}
2✔
929

930
TEST(Array_FindAllInt6)
931
{
2✔
932
    Array a(Allocator::get_default());
2✔
933
    a.create(Array::type_Normal);
2✔
934
    ArrayWithFind f(a);
2✔
935

936
    IntegerColumn r(Allocator::get_default());
2✔
937
    r.create();
2✔
938

939
    const int value = 70000;
2✔
940
    const int vReps = 5;
2✔
941

942
    for (int i = 0; i < vReps; ++i) {
12✔
943
        // 32 bitwidth
944
        a.add(70000);
10✔
945
        a.add(70001);
10✔
946
        a.add(70002);
10✔
947
        a.add(70003);
10✔
948
    }
10✔
949

950
    f.find_all(&r, value);
2✔
951
    CHECK_EQUAL(vReps, r.size());
2✔
952

953
    size_t i = 0;
2✔
954
    size_t j = 0;
2✔
955
    while (i < a.size()) {
42✔
956
        if (a.get(i) == value)
40✔
957
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
958
        i += 1;
40✔
959
    }
40✔
960

961
    // Cleanup
962
    a.destroy();
2✔
963
    r.destroy();
2✔
964
}
2✔
965

966
TEST(Array_FindAllInt7)
967
{
2✔
968
    Array a(Allocator::get_default());
2✔
969
    a.create(Array::type_Normal);
2✔
970
    ArrayWithFind f(a);
2✔
971

972
    IntegerColumn r(Allocator::get_default());
2✔
973
    r.create();
2✔
974

975
    const int64_t value = 4300000003ULL;
2✔
976
    const int vReps = 5;
2✔
977

978
    for (int i = 0; i < vReps; ++i) {
12✔
979
        // 64 bitwidth
980
        a.add(4300000000ULL);
10✔
981
        a.add(4300000001ULL);
10✔
982
        a.add(4300000002ULL);
10✔
983
        a.add(4300000003ULL);
10✔
984
    }
10✔
985

986
    f.find_all(&r, value);
2✔
987
    CHECK_EQUAL(vReps, r.size());
2✔
988

989
    size_t i = 0;
2✔
990
    size_t j = 0;
2✔
991
    while (i < a.size()) {
42✔
992
        if (a.get(i) == value)
40✔
993
            CHECK_EQUAL(int64_t(i), r.get(j++));
10✔
994
        i += 1;
40✔
995
    }
40✔
996

997
    // Cleanup
998
    a.destroy();
2✔
999
    r.destroy();
2✔
1000
}
2✔
1001

1002
// Tests the case where a value does *not* exist in one entire 64-bit chunk (triggers the 'if (has_zero_byte())
1003
// break;' condition)
1004
TEST(Array_FindHasZeroByte)
1005
{
2✔
1006
    // we want at least 1 entire 64-bit chunk-test, and we also want a remainder-test, so we chose n to be a prime >
1007
    // 64
1008
    size_t n = 73;
2✔
1009
    has_zero_byte(test_context, 1, n);            // width = 1
2✔
1010
    has_zero_byte(test_context, 3, n);            // width = 2
2✔
1011
    has_zero_byte(test_context, 13, n);           // width = 4
2✔
1012
    has_zero_byte(test_context, 100, n);          // 8
2✔
1013
    has_zero_byte(test_context, 10000, n);        // 16
2✔
1014
    has_zero_byte(test_context, 100000, n);       // 32
2✔
1015
    has_zero_byte(test_context, 8000000000LL, n); // 64
2✔
1016
}
2✔
1017

1018
// New find test for SSE search, to trigger partial finds (see find_sse()) before and after the aligned data area
1019
TEST(Array_find_sse)
1020
{
2✔
1021
    Array a(Allocator::get_default());
2✔
1022
    a.create(Array::type_Normal);
2✔
1023

1024
    for (uint64_t i = 0; i < 100; ++i) {
202✔
1025
        a.add(10000);
200✔
1026
    }
200✔
1027

1028
    for (size_t i = 0; i < 100; ++i) {
202✔
1029
        a.set(i, 123);
200✔
1030
        size_t t = a.find_first(123);
200✔
1031
        REALM_ASSERT(t == i);
200✔
1032
        a.set(i, 10000);
200✔
1033
        static_cast<void>(t);
200✔
1034
    }
200✔
1035
    a.destroy();
2✔
1036
}
2✔
1037

1038

1039
TEST(Array_Greater)
1040
{
2✔
1041
    Array a(Allocator::get_default());
2✔
1042
    a.create(Array::type_Normal);
2✔
1043

1044
    size_t items = 400;
2✔
1045

1046
    for (items = 2; items < 200; items += 7) {
60✔
1047

1048
        a.clear();
58✔
1049
        for (size_t i = 0; i < items; ++i) {
5,858✔
1050
            a.add(0);
5,800✔
1051
        }
5,800✔
1052

1053
        {
58✔
1054
            size_t t = a.find_first<Greater>(0, 0, size_t(-1));
58✔
1055
            CHECK_EQUAL(size_t(-1), t);
58✔
1056
        }
58✔
1057

1058
        a.clear();
58✔
1059
        for (size_t i = 0; i < items; ++i) {
5,858✔
1060
            a.add(0);
5,800✔
1061
        }
5,800✔
1062
        for (size_t i = 0; i < items; ++i) {
5,858✔
1063
            a.set(i, 1);
5,800✔
1064

1065
            size_t t = a.find_first<Greater>(0, 0, size_t(-1));
5,800✔
1066
            REALM_ASSERT(i == t);
5,800✔
1067

1068
            CHECK_EQUAL(i, t);
5,800✔
1069
            a.set(i, 0);
5,800✔
1070
        }
5,800✔
1071

1072
        a.clear();
58✔
1073
        for (size_t i = 0; i < items; ++i) {
5,858✔
1074
            a.add(2);
5,800✔
1075
        }
5,800✔
1076
        for (size_t i = 0; i < items; ++i) {
5,858✔
1077
            a.set(i, 3);
5,800✔
1078
            size_t t = a.find_first<Greater>(2, 0, size_t(-1));
5,800✔
1079
            CHECK_EQUAL(i, t);
5,800✔
1080
            a.set(i, 2);
5,800✔
1081
        }
5,800✔
1082

1083
        a.clear();
58✔
1084
        for (size_t i = 0; i < items; ++i) {
5,858✔
1085
            a.add(10);
5,800✔
1086
        }
5,800✔
1087
        for (size_t i = 0; i < items; ++i) {
5,858✔
1088
            a.set(i, 11);
5,800✔
1089
            size_t t = a.find_first<Greater>(10, 0, size_t(-1));
5,800✔
1090
            CHECK_EQUAL(i, t);
5,800✔
1091
            a.set(i, 10);
5,800✔
1092
        }
5,800✔
1093

1094
        a.clear();
58✔
1095
        for (size_t i = 0; i < items; ++i) {
5,858✔
1096
            a.add(100);
5,800✔
1097
        }
5,800✔
1098
        for (size_t i = 0; i < items; ++i) {
5,858✔
1099
            a.set(i, 110);
5,800✔
1100
            size_t t = a.find_first<Greater>(100, 0, size_t(-1));
5,800✔
1101
            CHECK_EQUAL(i, t);
5,800✔
1102
            a.set(i, 100);
5,800✔
1103
        }
5,800✔
1104
        a.clear();
58✔
1105
        for (size_t i = 0; i < items; ++i) {
5,858✔
1106
            a.add(200);
5,800✔
1107
        }
5,800✔
1108
        for (size_t i = 0; i < items; ++i) {
5,858✔
1109
            a.set(i, 210);
5,800✔
1110
            size_t t = a.find_first<Greater>(200, 0, size_t(-1));
5,800✔
1111
            CHECK_EQUAL(i, t);
5,800✔
1112
            a.set(i, 200);
5,800✔
1113
        }
5,800✔
1114

1115
        a.clear();
58✔
1116
        for (size_t i = 0; i < items; ++i) {
5,858✔
1117
            a.add(10000);
5,800✔
1118
        }
5,800✔
1119
        for (size_t i = 0; i < items; ++i) {
5,858✔
1120
            a.set(i, 11000);
5,800✔
1121
            size_t t = a.find_first<Greater>(10000, 0, size_t(-1));
5,800✔
1122
            CHECK_EQUAL(i, t);
5,800✔
1123
            a.set(i, 10000);
5,800✔
1124
        }
5,800✔
1125
        a.clear();
58✔
1126
        for (size_t i = 0; i < items; ++i) {
5,858✔
1127
            a.add(40000);
5,800✔
1128
        }
5,800✔
1129

1130
        for (size_t i = 0; i < items; ++i) {
5,858✔
1131
            a.set(i, 41000);
5,800✔
1132
            size_t t = a.find_first<Greater>(40000, 0, size_t(-1));
5,800✔
1133
            CHECK_EQUAL(i, t);
5,800✔
1134
            a.set(i, 40000);
5,800✔
1135
        }
5,800✔
1136

1137
        a.clear();
58✔
1138
        for (size_t i = 0; i < items; ++i) {
5,858✔
1139
            a.add(1000000);
5,800✔
1140
        }
5,800✔
1141
        for (size_t i = 0; i < items; ++i) {
5,858✔
1142
            a.set(i, 1100000);
5,800✔
1143
            size_t t = a.find_first<Greater>(1000000, 0, size_t(-1));
5,800✔
1144
            CHECK_EQUAL(i, t);
5,800✔
1145
            a.set(i, 1000000);
5,800✔
1146
        }
5,800✔
1147

1148
        a.clear();
58✔
1149
        for (size_t i = 0; i < items; ++i) {
5,858✔
1150
            a.add(1000ULL * 1000ULL * 1000ULL * 1000ULL);
5,800✔
1151
        }
5,800✔
1152
        for (size_t i = 0; i < items; ++i) {
5,858✔
1153
            a.set(i, 1000ULL * 1000ULL * 1000ULL * 1000ULL + 1ULL);
5,800✔
1154
            size_t t = a.find_first<Greater>(1000ULL * 1000ULL * 1000ULL * 1000ULL, 0, size_t(-1));
5,800✔
1155
            CHECK_EQUAL(i, t);
5,800✔
1156
            a.set(i, 1000ULL * 1000ULL * 1000ULL * 1000ULL);
5,800✔
1157
        }
5,800✔
1158
    }
58✔
1159
    a.destroy();
2✔
1160
}
2✔
1161

1162

1163
TEST(Array_Less)
1164
{
2✔
1165
    Array a(Allocator::get_default());
2✔
1166
    a.create(Array::type_Normal);
2✔
1167

1168
    size_t items = 400;
2✔
1169

1170
    for (items = 2; items < 200; items += 7) {
60✔
1171

1172
        a.clear();
58✔
1173
        for (size_t i = 0; i < items; ++i) {
5,858✔
1174
            a.add(0);
5,800✔
1175
        }
5,800✔
1176

1177
        {
58✔
1178
            size_t t = a.find_first<Less>(0, 0, size_t(-1));
58✔
1179
            CHECK_EQUAL(size_t(-1), t);
58✔
1180
        }
58✔
1181

1182
        a.clear();
58✔
1183
        for (size_t i = 0; i < items; ++i) {
5,858✔
1184
            a.add(1);
5,800✔
1185
        }
5,800✔
1186
        for (size_t i = 0; i < items; ++i) {
5,858✔
1187
            a.set(i, 0);
5,800✔
1188
            size_t t = a.find_first<Less>(1, 0, size_t(-1));
5,800✔
1189
            CHECK_EQUAL(i, t);
5,800✔
1190
            a.set(i, 1);
5,800✔
1191
        }
5,800✔
1192

1193
        a.clear();
58✔
1194
        for (size_t i = 0; i < items; ++i) {
5,858✔
1195
            a.add(3);
5,800✔
1196
        }
5,800✔
1197
        for (size_t i = 0; i < items; ++i) {
5,858✔
1198
            a.set(i, 2);
5,800✔
1199
            size_t t = a.find_first<Less>(3, 0, size_t(-1));
5,800✔
1200
            CHECK_EQUAL(i, t);
5,800✔
1201
            a.set(i, 3);
5,800✔
1202
        }
5,800✔
1203

1204
        a.clear();
58✔
1205
        for (size_t i = 0; i < items; ++i) {
5,858✔
1206
            a.add(11);
5,800✔
1207
        }
5,800✔
1208
        for (size_t i = 0; i < items; ++i) {
5,858✔
1209
            a.set(i, 10);
5,800✔
1210
            size_t t = a.find_first<Less>(11, 0, size_t(-1));
5,800✔
1211
            CHECK_EQUAL(i, t);
5,800✔
1212
            a.set(i, 11);
5,800✔
1213
        }
5,800✔
1214

1215
        a.clear();
58✔
1216
        for (size_t i = 0; i < items; ++i) {
5,858✔
1217
            a.add(110);
5,800✔
1218
        }
5,800✔
1219
        for (size_t i = 0; i < items; ++i) {
5,858✔
1220
            a.set(i, 100);
5,800✔
1221
            size_t t = a.find_first<Less>(110, 0, size_t(-1));
5,800✔
1222
            CHECK_EQUAL(i, t);
5,800✔
1223
            a.set(i, 110);
5,800✔
1224
        }
5,800✔
1225
        a.clear();
58✔
1226
        for (size_t i = 0; i < items; ++i) {
5,858✔
1227
            a.add(210);
5,800✔
1228
        }
5,800✔
1229
        for (size_t i = 0; i < items; ++i) {
5,858✔
1230
            a.set(i, 200);
5,800✔
1231
            size_t t = a.find_first<Less>(210, 0, size_t(-1));
5,800✔
1232
            CHECK_EQUAL(i, t);
5,800✔
1233
            a.set(i, 210);
5,800✔
1234
        }
5,800✔
1235

1236
        a.clear();
58✔
1237
        for (size_t i = 0; i < items; ++i) {
5,858✔
1238
            a.add(11000);
5,800✔
1239
        }
5,800✔
1240
        for (size_t i = 0; i < items; ++i) {
5,858✔
1241
            a.set(i, 10000);
5,800✔
1242
            size_t t = a.find_first<Less>(11000, 0, size_t(-1));
5,800✔
1243
            CHECK_EQUAL(i, t);
5,800✔
1244
            a.set(i, 11000);
5,800✔
1245
        }
5,800✔
1246
        a.clear();
58✔
1247
        for (size_t i = 0; i < items; ++i) {
5,858✔
1248
            a.add(41000);
5,800✔
1249
        }
5,800✔
1250

1251
        for (size_t i = 0; i < items; ++i) {
5,858✔
1252
            a.set(i, 40000);
5,800✔
1253
            size_t t = a.find_first<Less>(41000, 0, size_t(-1));
5,800✔
1254
            CHECK_EQUAL(i, t);
5,800✔
1255
            a.set(i, 41000);
5,800✔
1256
        }
5,800✔
1257

1258
        a.clear();
58✔
1259
        for (size_t i = 0; i < items; ++i) {
5,858✔
1260
            a.add(1100000);
5,800✔
1261
        }
5,800✔
1262
        for (size_t i = 0; i < items; ++i) {
5,858✔
1263
            a.set(i, 1000000);
5,800✔
1264
            size_t t = a.find_first<Less>(1100000, 0, size_t(-1));
5,800✔
1265
            CHECK_EQUAL(i, t);
5,800✔
1266
            a.set(i, 1100000);
5,800✔
1267
        }
5,800✔
1268

1269
        a.clear();
58✔
1270
        for (size_t i = 0; i < items; ++i) {
5,858✔
1271
            a.add(1000ULL * 1000ULL * 1000ULL * 1000ULL);
5,800✔
1272
        }
5,800✔
1273
        for (size_t i = 0; i < items; ++i) {
5,858✔
1274
            a.set(i, 1000ULL * 1000ULL * 1000ULL * 1000ULL - 1ULL);
5,800✔
1275
            size_t t = a.find_first<Less>(1000ULL * 1000ULL * 1000ULL * 1000ULL, 0, size_t(-1));
5,800✔
1276
            CHECK_EQUAL(i, t);
5,800✔
1277
            a.set(i, 1000ULL * 1000ULL * 1000ULL * 1000ULL);
5,800✔
1278
        }
5,800✔
1279
    }
58✔
1280
    a.destroy();
2✔
1281
}
2✔
1282

1283

1284
TEST(Array_NotEqual1)
1285
{
2✔
1286
    Array a(Allocator::get_default());
2✔
1287
    a.create(Array::type_Normal);
2✔
1288

1289
    a.clear();
2✔
1290
    for (size_t i = 0; i < 100; ++i) {
202✔
1291
        a.add(0x33);
200✔
1292
    }
200✔
1293
    a.set(50, 0x44);
2✔
1294
    size_t t = a.find_first<NotEqual>(0x33, 0, size_t(-1));
2✔
1295
    CHECK_EQUAL(50, t);
2✔
1296
    a.destroy();
2✔
1297
}
2✔
1298

1299
TEST(Array_NotEqual)
1300
{
2✔
1301
    Array a(Allocator::get_default());
2✔
1302
    a.create(Array::type_Normal);
2✔
1303

1304
    size_t items = 400;
2✔
1305

1306
    for (items = 2; items < 200; items += 7) {
60✔
1307
        a.clear();
58✔
1308
        for (size_t i = 0; i < items; ++i) {
5,858✔
1309
            a.add(0);
5,800✔
1310
        }
5,800✔
1311

1312
        {
58✔
1313
            size_t t = a.find_first<NotEqual>(0, 0, size_t(-1));
58✔
1314
            CHECK_EQUAL(size_t(-1), t);
58✔
1315
        }
58✔
1316

1317
        a.clear();
58✔
1318
        for (size_t i = 0; i < items; ++i) {
5,858✔
1319
            a.add(0);
5,800✔
1320
        }
5,800✔
1321
        for (size_t i = 0; i < items; ++i) {
5,858✔
1322
            a.set(i, 1);
5,800✔
1323
            size_t t = a.find_first<NotEqual>(0, 0, size_t(-1));
5,800✔
1324
            CHECK_EQUAL(i, t);
5,800✔
1325
            a.set(i, 0);
5,800✔
1326
        }
5,800✔
1327

1328
        a.clear();
58✔
1329
        for (size_t i = 0; i < items; ++i) {
5,858✔
1330
            a.add(2);
5,800✔
1331
        }
5,800✔
1332
        for (size_t i = 0; i < items; ++i) {
5,858✔
1333
            a.set(i, 3);
5,800✔
1334
            size_t t = a.find_first<NotEqual>(2, 0, size_t(-1));
5,800✔
1335
            CHECK_EQUAL(i, t);
5,800✔
1336
            a.set(i, 2);
5,800✔
1337
        }
5,800✔
1338

1339
        a.clear();
58✔
1340
        for (size_t i = 0; i < items; ++i) {
5,858✔
1341
            a.add(10);
5,800✔
1342
        }
5,800✔
1343
        for (size_t i = 0; i < items; ++i) {
5,858✔
1344
            a.set(i, 11);
5,800✔
1345
            size_t t = a.find_first<NotEqual>(10, 0, size_t(-1));
5,800✔
1346
            CHECK_EQUAL(i, t);
5,800✔
1347
            a.set(i, 10);
5,800✔
1348
        }
5,800✔
1349

1350
        a.clear();
58✔
1351
        for (size_t i = 0; i < items; ++i) {
5,858✔
1352
            a.add(100);
5,800✔
1353
        }
5,800✔
1354
        for (size_t i = 0; i < items; ++i) {
5,858✔
1355
            a.set(i, 110);
5,800✔
1356
            size_t t = a.find_first<NotEqual>(100, 0, size_t(-1));
5,800✔
1357
            CHECK_EQUAL(i, t);
5,800✔
1358
            a.set(i, 100);
5,800✔
1359
        }
5,800✔
1360
        a.clear();
58✔
1361
        for (size_t i = 0; i < items; ++i) {
5,858✔
1362
            a.add(200);
5,800✔
1363
        }
5,800✔
1364
        for (size_t i = 0; i < items; ++i) {
5,858✔
1365
            a.set(i, 210);
5,800✔
1366
            size_t t = a.find_first<NotEqual>(200, 0, size_t(-1));
5,800✔
1367
            CHECK_EQUAL(i, t);
5,800✔
1368
            a.set(i, 200);
5,800✔
1369
        }
5,800✔
1370

1371
        a.clear();
58✔
1372
        for (size_t i = 0; i < items; ++i) {
5,858✔
1373
            a.add(10000);
5,800✔
1374
        }
5,800✔
1375
        for (size_t i = 0; i < items; ++i) {
5,858✔
1376
            a.set(i, 11000);
5,800✔
1377
            size_t t = a.find_first<NotEqual>(10000, 0, size_t(-1));
5,800✔
1378
            CHECK_EQUAL(i, t);
5,800✔
1379
            a.set(i, 10000);
5,800✔
1380
        }
5,800✔
1381
        a.clear();
58✔
1382
        for (size_t i = 0; i < items; ++i) {
5,858✔
1383
            a.add(40000);
5,800✔
1384
        }
5,800✔
1385

1386
        for (size_t i = 0; i < items; ++i) {
5,858✔
1387
            a.set(i, 41000);
5,800✔
1388
            size_t t = a.find_first<NotEqual>(40000, 0, size_t(-1));
5,800✔
1389
            CHECK_EQUAL(i, t);
5,800✔
1390
            a.set(i, 40000);
5,800✔
1391
        }
5,800✔
1392

1393
        a.clear();
58✔
1394
        for (size_t i = 0; i < items; ++i) {
5,858✔
1395
            a.add(1000000);
5,800✔
1396
        }
5,800✔
1397
        for (size_t i = 0; i < items; ++i) {
5,858✔
1398
            a.set(i, 1100000);
5,800✔
1399
            size_t t = a.find_first<NotEqual>(1000000, 0, size_t(-1));
5,800✔
1400
            CHECK_EQUAL(i, t);
5,800✔
1401
            a.set(i, 1000000);
5,800✔
1402
        }
5,800✔
1403

1404
        a.clear();
58✔
1405
        for (size_t i = 0; i < items; ++i) {
5,858✔
1406
            a.add(1000ULL * 1000ULL * 1000ULL * 1000ULL);
5,800✔
1407
        }
5,800✔
1408
        for (size_t i = 0; i < items; ++i) {
5,858✔
1409
            a.set(i, 1000ULL * 1000ULL * 1000ULL * 1000ULL + 1ULL);
5,800✔
1410
            size_t t = a.find_first<NotEqual>(1000ULL * 1000ULL * 1000ULL * 1000ULL, 0, size_t(-1));
5,800✔
1411
            CHECK_EQUAL(i, t);
5,800✔
1412
            a.set(i, 1000ULL * 1000ULL * 1000ULL * 1000ULL);
5,800✔
1413
        }
5,800✔
1414
    }
58✔
1415
    a.destroy();
2✔
1416
}
2✔
1417

1418

1419
TEST(Array_Large)
1420
{
2✔
1421
    Array c(Allocator::get_default());
2✔
1422
    c.create(Array::type_Normal);
2✔
1423

1424
    // TEST(Array_Add0)
1425

1426
    c.add(0x1234567890);
2✔
1427
    for (int i = 0; i < 0x300000; i++) {
6,291,458✔
1428
        c.add(i);
6,291,456✔
1429
    }
6,291,456✔
1430
    CHECK_EQUAL(c.size(), 0x300001);
2✔
1431
    CHECK_EQUAL(c.get(0x300000), 0x300000 - 1);
2✔
1432
    c.destroy();
2✔
1433
}
2✔
1434

1435
TEST(Array_set_type)
1436
{
2✔
1437
    Array c(Allocator::get_default());
2✔
1438
    c.create(Array::type_Normal);
2✔
1439

1440
    c.set_type(Array::type_Normal);
2✔
1441
    CHECK_EQUAL(c.get_type(), Array::type_Normal);
2✔
1442

1443
    c.set_type(Array::type_InnerBptreeNode);
2✔
1444
    CHECK_EQUAL(c.get_type(), Array::type_InnerBptreeNode);
2✔
1445

1446
    c.set_type(Array::type_HasRefs);
2✔
1447
    CHECK_EQUAL(c.get_type(), Array::type_HasRefs);
2✔
1448

1449
    c.destroy();
2✔
1450
}
2✔
1451

1452
TEST(Array_get_sum)
1453
{
2✔
1454
    Array c(Allocator::get_default());
2✔
1455
    c.create(Array::type_Normal);
2✔
1456

1457
    // simple sum1
1458
    for (int i = 0; i < 0x10; i++)
34✔
1459
        c.add(i);
32✔
1460
    CHECK_EQUAL(c.get_sum(), 120);
2✔
1461
    c.clear();
2✔
1462

1463
    const auto size = realm::max_array_size / 4;
2✔
1464

1465
    // test multiple chunks w=1
1466
    for (uint64_t i = 0; i < size; ++i)
8,388,608✔
1467
        c.add(0x1);
8,388,606✔
1468
    CHECK_EQUAL(c.get_sum(), size);
2✔
1469

1470
    // test multiple chunks w=2
1471
    c.clear();
2✔
1472
    for (uint64_t i = 0; i < size; ++i)
8,388,608✔
1473
        c.add(0x3);
8,388,606✔
1474
    CHECK_EQUAL(c.get_sum(), 0x3 * size);
2✔
1475

1476
    // test multiple chunks w=4
1477
    c.clear();
2✔
1478
    for (uint64_t i = 0; i < size; ++i)
8,388,608✔
1479
        c.add(0x13);
8,388,606✔
1480
    CHECK_EQUAL(c.get_sum(), 0x13 * size);
2✔
1481

1482
    // test multiple chunks w=8
1483
    c.clear();
2✔
1484
    for (uint64_t i = 0; i < size; ++i)
8,388,608✔
1485
        c.add(0x100);
8,388,606✔
1486
    CHECK_EQUAL(c.get_sum(), 0x100 * size);
2✔
1487

1488
    // test multiple chunks w=16
1489
    c.clear();
2✔
1490
    for (uint64_t i = 0; i < size; ++i) {
8,388,608✔
1491
        c.add(0x10000);
8,388,606✔
1492
    }
8,388,606✔
1493
    CHECK_EQUAL(c.get_sum(), 0x10000LL * size);
2✔
1494

1495
    // test multiple chunks w=32
1496
    c.clear();
2✔
1497
    for (uint64_t i = 0; i < size; ++i)
8,388,608✔
1498
        c.add(0x100000);
8,388,606✔
1499
    CHECK_EQUAL(c.get_sum(), 0x100000LL * size);
2✔
1500

1501
    // test multiple chunks w=64
1502
    c.clear();
2✔
1503
    for (uint64_t i = 0; i < size; ++i)
8,388,608✔
1504
        c.add(8000000000LL);
8,388,606✔
1505
    CHECK_EQUAL(c.get_sum(), (size * 8000000000LL));
2✔
1506

1507
    // test generic case
1508
    c.clear();
2✔
1509
    uint64_t expected = 0;
2✔
1510
    for (uint64_t i = 0; i < 0x30000; ++i) {
393,218✔
1511
        c.add(i);
393,216✔
1512
        expected += i;
393,216✔
1513
    }
393,216✔
1514
    CHECK_EQUAL(c.get_sum(), expected);
2✔
1515

1516
    c.destroy();
2✔
1517
}
2✔
1518

1519
// NONCONCURRENT because if run in parallel with other tests which request large amounts of
1520
// memory, there may be a std::bad_alloc on low memory machines
1521
NONCONCURRENT_TEST(Array_count)
1522
{
2✔
1523
    struct TestArray : public Array {
2✔
1524
        explicit TestArray(Allocator& allocator)
2✔
1525
            : Array(allocator)
2✔
1526
        {
2✔
1527
        }
2✔
1528
        size_t count(int64_t v)
2✔
1529
        {
14✔
1530
            return Array::count(v);
14✔
1531
        }
14✔
1532
    };
2✔
1533

1534
    TestArray c(Allocator::get_default());
2✔
1535
    c.create(Array::type_Normal);
2✔
1536
    const size_t size = realm::max_array_size;
2✔
1537

1538
    // test multiple chunks w=1
1539
    c.clear();
2✔
1540
    for (uint64_t i = 0; i < size; ++i)
33,554,432✔
1541
        c.add(0x1);
33,554,430✔
1542
    CHECK_EQUAL(c.count(0x1), size);
2✔
1543

1544
    // test multiple chunks w=2
1545
    c.clear();
2✔
1546
    for (uint64_t i = 0; i < size; ++i)
33,554,432✔
1547
        c.add(0x3);
33,554,430✔
1548
    CHECK_EQUAL(c.count(0x3), size);
2✔
1549

1550
    // test multiple chunks w=4
1551
    c.clear();
2✔
1552
    for (uint64_t i = 0; i < size; ++i)
33,554,432✔
1553
        c.add(0x13);
33,554,430✔
1554
    CHECK_EQUAL(c.count(0x13), size);
2✔
1555

1556
    // test multiple chunks w=8
1557
    c.clear();
2✔
1558
    for (uint64_t i = 0; i < size; ++i)
33,554,432✔
1559
        c.add(0x100);
33,554,430✔
1560
    CHECK_EQUAL(c.count(0x100), size);
2✔
1561

1562
    // test multiple chunks w=16
1563
    c.clear();
2✔
1564
    for (uint64_t i = 0; i < size; ++i)
33,554,432✔
1565
        c.add(0x10000);
33,554,430✔
1566
    CHECK_EQUAL(c.count(0x10000), size);
2✔
1567

1568
    // test w=32 (number of chunks does not matter)
1569
    c.clear();
2✔
1570
    const size_t size_32_64_bit = 10;
2✔
1571
    for (uint64_t i = 0; i < size_32_64_bit; ++i)
22✔
1572
        c.add(100000);
20✔
1573
    CHECK_EQUAL(c.count(100000), size_32_64_bit);
2✔
1574

1575
    // test w=64 (number of chunks does not matter)
1576
    c.clear();
2✔
1577
    for (uint64_t i = 0; i < size_32_64_bit; ++i)
22✔
1578
        c.add(8000000000LL);
20✔
1579
    CHECK_EQUAL(c.count(8000000000LL), size_32_64_bit);
2✔
1580

1581
    c.destroy();
2✔
1582
}
2✔
1583

1584
TEST(DirectBitFields)
1585
{
2✔
1586
    uint64_t a[2];
2✔
1587
    a[0] = a[1] = 0;
2✔
1588
    {
2✔
1589
        BfIterator it(a, 0, 7, 7, 8);
2✔
1590
        REALM_ASSERT(*it == 0);
2✔
1591
        auto it2(it);
2✔
1592
        ++it2;
2✔
1593
        it2.set_value(127 + 128);
2✔
1594
        REALM_ASSERT(*it == 0);
2✔
1595
        ++it;
2✔
1596
        REALM_ASSERT(*it == 127);
2✔
1597
        ++it;
2✔
1598
        REALM_ASSERT(*it == 0);
2✔
1599
    }
2✔
1600
    // reverse polarity
1601
    a[0] = a[1] = -1ULL;
2✔
1602
    {
2✔
1603
        BfIterator it(a, 0, 7, 7, 8);
2✔
1604
        REALM_ASSERT(*it == 127);
2✔
1605
        auto it2(it);
2✔
1606
        ++it2;
2✔
1607
        it2.set_value(42 + 128);
2✔
1608
        REALM_ASSERT(*it == 127);
2✔
1609
        ++it;
2✔
1610
        REALM_ASSERT(*it == 42);
2✔
1611
        ++it;
2✔
1612
        REALM_ASSERT(*it == 127);
2✔
1613
    }
2✔
1614
}
2✔
1615

1616
TEST(Extended_Array_encoding)
1617
{
2✔
1618
    using Encoding = NodeHeader::Encoding;
2✔
1619
    Array array(Allocator::get_default());
2✔
1620
    auto mem = array.get_alloc().alloc(10);
2✔
1621
    init_header(mem.get_addr(), Encoding::Flex, 7, 1, 1, 1, 1);
2✔
1622
    array.init_from_mem(mem);
2✔
1623
    auto array_header = array.get_header();
2✔
1624
    auto encoding = array.get_encoding(array_header);
2✔
1625
    CHECK(encoding == Encoding::Flex);
2✔
1626

1627
    Array another_array(Allocator::get_default());
2✔
1628
    another_array.init_from_ref(array.get_ref());
2✔
1629
    auto another_header = another_array.get_header();
2✔
1630
    auto another_encoding = another_array.get_encoding(another_header);
2✔
1631
    CHECK(encoding == another_encoding);
2✔
1632

1633
    array.get_alloc().free_(mem);
2✔
1634
}
2✔
1635

1636
TEST(Array_cares_about)
1637
{
2✔
1638
    std::vector<uint64_t> expected{
2✔
1639
        0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff, 0xffffffffffffffff,
2✔
1640
        0xfffffffffffffff,  0xfffffffffffffff,  0x7fffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff,
2✔
1641
        0xfffffffffffffff,  0x7fffffffffffff,   0xfffffffffffffff,  0xfffffffffffff,    0xffffffffffffff,
2✔
1642
        0xfffffffffffffff,  0xffffffffffffffff, 0x7ffffffffffff,    0x3fffffffffffff,   0x1ffffffffffffff,
2✔
1643
        0xfffffffffffffff,  0x7fffffffffffffff, 0xfffffffffff,      0x3fffffffffff,     0xffffffffffff,
2✔
1644
        0x3ffffffffffff,    0xfffffffffffff,    0x3fffffffffffff,   0xffffffffffffff,   0x3ffffffffffffff,
2✔
1645
        0xfffffffffffffff,  0x3fffffffffffffff, 0xffffffffffffffff, 0x1ffffffff,        0x3ffffffff,
2✔
1646
        0x7ffffffff,        0xfffffffff,        0x1fffffffff,       0x3fffffffff,       0x7fffffffff,
2✔
1647
        0xffffffffff,       0x1ffffffffff,      0x3ffffffffff,      0x7ffffffffff,      0xfffffffffff,
2✔
1648
        0x1fffffffffff,     0x3fffffffffff,     0x7fffffffffff,     0xffffffffffff,     0x1ffffffffffff,
2✔
1649
        0x3ffffffffffff,    0x7ffffffffffff,    0xfffffffffffff,    0x1fffffffffffff,   0x3fffffffffffff,
2✔
1650
        0x7fffffffffffff,   0xffffffffffffff,   0x1ffffffffffffff,  0x3ffffffffffffff,  0x7ffffffffffffff,
2✔
1651
        0xfffffffffffffff,  0x1fffffffffffffff, 0x3fffffffffffffff, 0x7fffffffffffffff, 0xffffffffffffffff};
2✔
1652
    std::vector<uint64_t> res;
2✔
1653
    for (uint8_t i = 0; i <= 64; i++) {
132✔
1654
        res.push_back(cares_about(i));
130✔
1655
    }
130✔
1656
    CHECK_EQUAL(res, expected);
2✔
1657
}
2✔
1658

1659
TEST(AlignDirectBitFields)
1660
{
2✔
1661
    uint64_t a[2];
2✔
1662
    a[0] = a[1] = 0;
2✔
1663
    {
2✔
1664
        BfIterator it(a, 0, 7, 7, 8);
2✔
1665
        REALM_ASSERT(*it == 0);
2✔
1666
        auto it2(it);
2✔
1667
        ++it2;
2✔
1668
        it2.set_value(127 + 128);
2✔
1669
        REALM_ASSERT(*it == 0);
2✔
1670
        ++it;
2✔
1671
        REALM_ASSERT(*it == 127);
2✔
1672
        ++it;
2✔
1673
        REALM_ASSERT(*it == 0);
2✔
1674
    }
2✔
1675
    // reverse polarity
1676
    a[0] = a[1] = -1ULL;
2✔
1677
    {
2✔
1678
        BfIterator it(a, 0, 7, 7, 8);
2✔
1679
        REALM_ASSERT(*it == 127);
2✔
1680
        auto it2(it);
2✔
1681
        ++it2;
2✔
1682
        it2.set_value(42 + 128);
2✔
1683
        REALM_ASSERT(*it == 127);
2✔
1684
        ++it;
2✔
1685
        REALM_ASSERT(*it == 42);
2✔
1686
        ++it;
2✔
1687
        REALM_ASSERT(*it == 127);
2✔
1688
    }
2✔
1689
}
2✔
1690

1691
TEST(TestSignValuesStoredIterator)
1692
{
2✔
1693
    {
2✔
1694
        // positive values are easy.
1695
        uint64_t a[2];
2✔
1696
        BfIterator it(a, 0, 8, 8, 0);
2✔
1697
        for (size_t i = 0; i < 16; ++i) {
34✔
1698
            it.set_value(i);
32✔
1699
            ++it;
32✔
1700
        }
32✔
1701
        it.move(0);
2✔
1702
        for (size_t i = 0; i < 16; ++i) {
34✔
1703
            auto v = *it;
32✔
1704
            CHECK_EQUAL(v, i);
32✔
1705
            ++it;
32✔
1706
        }
32✔
1707
    }
2✔
1708
    {
2✔
1709
        // negative values require a bit more work
1710
        uint64_t a[2];
2✔
1711
        BfIterator it(a, 0, 8, 8, 0);
2✔
1712
        for (size_t i = 0; i < 16; ++i) {
34✔
1713
            it.set_value(-i);
32✔
1714
            ++it;
32✔
1715
        }
32✔
1716
        it.move(0);
2✔
1717
        for (int64_t i = 0; i < 16; ++i) {
34✔
1718
            const auto sv = sign_extend_value(8, *it);
32✔
1719
            CHECK_EQUAL(sv, -i);
32✔
1720
            ++it;
32✔
1721
        }
32✔
1722
        it.move(0);
2✔
1723
        const auto sign_mask = 1ULL << (7);
2✔
1724
        for (int64_t i = 0; i < 16; ++i) {
34✔
1725
            const auto sv = sign_extend_field_by_mask(sign_mask, *it);
32✔
1726
            CHECK_EQUAL(sv, -i);
32✔
1727
            ++it;
32✔
1728
        }
32✔
1729
    }
2✔
1730
}
2✔
1731

1732
TEST(VerifyIterationAcrossWords)
1733
{
2✔
1734
    uint64_t a[4]{0, 0, 0, 0}; // 4 64 bit words, let's store N elements of 5bits each
2✔
1735
    BfIterator it(a, 0, 5, 5, 0);
2✔
1736
    // 51 is the max amount of values we can fit in 4 words. Writting beyond this point is likely going
1737
    // to crash. Writing beyond the 4 words is not possible in practice because the Array has boundery checks
1738
    // and enough memory is reserved during compression.
1739
    srand((unsigned)time(0)); // no need to use complex stuff
2✔
1740
    std::vector<int64_t> values;
2✔
1741
    for (size_t i = 0; i < 51; i++) {
104✔
1742
        int64_t randomNumber = rand() % 16; // max value that can fit in 5 bits (4 bit for the value + 1 sign)
102✔
1743
        values.push_back(randomNumber);
102✔
1744
        it.set_value(randomNumber);
102✔
1745
        ++it;
102✔
1746
    }
102✔
1747

1748
    {
2✔
1749
        // normal bf iterator
1750
        it.move(0); // reset to first value.
2✔
1751
        // go through the memory, 5 bits by 5 bits.
1752
        // every 12 values, we will read the value across
1753
        // 2 words.
1754
        for (size_t i = 0; i < 51; ++i) {
104✔
1755
            const auto v = sign_extend_value(5, *it);
102✔
1756
            CHECK_EQUAL(v, values[i]);
102✔
1757
            ++it;
102✔
1758
        }
102✔
1759
    }
2✔
1760

1761
    {
2✔
1762
        // unaligned iterator
1763
        UnalignedWordIter u_it(a, 0);
2✔
1764
        for (size_t i = 0; i < 51; ++i) {
104✔
1765
            const auto v = sign_extend_value(5, u_it.consume(5) & 0x1F);
102✔
1766
            CHECK_EQUAL(v, values[i]);
102✔
1767
        }
102✔
1768
    }
2✔
1769
}
2✔
1770

1771
TEST(LowerBoundCorrectness)
1772
{
2✔
1773
    constexpr auto size = 16;
2✔
1774
    int64_t a[size]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
2✔
1775

1776
    std::vector<size_t> expected_default_lb;
2✔
1777
    for (const auto v : a) {
32✔
1778
        const auto pos = lower_bound<64>((const char*)(&a), size, v);
32✔
1779
        expected_default_lb.push_back(pos);
32✔
1780
    }
32✔
1781

1782
    // now simulate the compression of a in less bits
1783
    uint64_t buff[2] = {0, 0};
2✔
1784
    BfIterator it(buff, 0, 5, 5, 0); // 5 bits because 4 bits for the values + 1 bit for the sign
2✔
1785
    for (size_t i = 0; i < 16; ++i) {
34✔
1786
        it.set_value(i);
32✔
1787
        CHECK_EQUAL(*it, a[i]);
32✔
1788
        ++it;
32✔
1789
    }
32✔
1790
    struct MyClass {
2✔
1791
        uint64_t* _data;
2✔
1792
        int64_t get(size_t ndx) const
2✔
1793
        {
192✔
1794
            BfIterator it(_data, 0, 5, 5, ndx);
192✔
1795
            return sign_extend_value(5, *it);
192✔
1796
        }
192✔
1797
    };
2✔
1798
    // a bit of set up here.
1799
    MyClass my_class;
2✔
1800
    my_class._data = buff;
2✔
1801
    using Fetcher = impl::CompressedDataFetcher<MyClass>;
2✔
1802
    Fetcher my_fetcher;
2✔
1803
    my_fetcher.ptr = &my_class;
2✔
1804

1805
    // verify that the fetcher returns the same values
1806
    for (size_t i = 0; i < size; ++i) {
34✔
1807
        CHECK_EQUAL(my_fetcher.ptr->get(i), a[i]);
32✔
1808
    }
32✔
1809

1810
    std::vector<size_t> diffent_width_lb;
2✔
1811
    for (const auto v : a) {
32✔
1812
        const auto pos = lower_bound((const char*)buff, size, v, my_fetcher);
32✔
1813
        diffent_width_lb.push_back(pos);
32✔
1814
    }
32✔
1815

1816
    CHECK_EQUAL(expected_default_lb, diffent_width_lb);
2✔
1817
}
2✔
1818

1819
TEST(UpperBoundCorrectness)
1820
{
2✔
1821
    constexpr auto size = 16;
2✔
1822
    int64_t a[size]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
2✔
1823
    std::vector<size_t> expected_default_ub;
2✔
1824
    for (const auto v : a) {
32✔
1825
        const auto pos = upper_bound<64>((const char*)(&a), size, v);
32✔
1826
        expected_default_ub.push_back(pos);
32✔
1827
    }
32✔
1828

1829
    // now simulate the compression of a in less bits
1830
    uint64_t buff[2] = {0, 0};
2✔
1831
    BfIterator it(buff, 0, 5, 5, 0); // 5 bits because 4 bits for the values + 1 bit for the sign
2✔
1832
    for (size_t i = 0; i < size; ++i) {
34✔
1833
        it.set_value(i);
32✔
1834
        CHECK_EQUAL(*it, a[i]);
32✔
1835
        ++it;
32✔
1836
    }
32✔
1837
    struct MyClass {
2✔
1838
        uint64_t* _data;
2✔
1839
        int64_t get(size_t ndx) const
2✔
1840
        {
192✔
1841
            BfIterator it(_data, 0, 5, 5, ndx);
192✔
1842
            return sign_extend_value(5, *it);
192✔
1843
        }
192✔
1844
    };
2✔
1845
    // a bit of set up here.
1846
    MyClass my_class;
2✔
1847
    my_class._data = buff;
2✔
1848
    using Fetcher = impl::CompressedDataFetcher<MyClass>;
2✔
1849
    Fetcher my_fetcher;
2✔
1850
    my_fetcher.ptr = &my_class;
2✔
1851

1852
    // verify that the fetcher returns the same values
1853
    for (size_t i = 0; i < size; ++i) {
34✔
1854
        CHECK_EQUAL(my_fetcher.ptr->get(i), a[i]);
32✔
1855
    }
32✔
1856

1857
    std::vector<size_t> diffent_width_ub;
2✔
1858
    for (const auto v : a) {
32✔
1859
        const auto pos = upper_bound((const char*)buff, size, v, my_fetcher);
32✔
1860
        diffent_width_ub.push_back(pos);
32✔
1861
    }
32✔
1862

1863
    CHECK_EQUAL(expected_default_ub, diffent_width_ub);
2✔
1864
}
2✔
1865

1866
TEST(ParallelSearchEqualMatch)
1867
{
2✔
1868
    std::mt19937_64 gen64;
2✔
1869
    constexpr size_t buflen = 4;
2✔
1870
    uint64_t buff[buflen];
2✔
1871
    std::vector<int64_t> values;
2✔
1872
    for (uint8_t width = 1; width <= 64; width++) {
130✔
1873
        const size_t size = (buflen * 64) / width;
128✔
1874
        const uint64_t bit_mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - width); // (1ULL << width) - 1;
128✔
1875

1876
        values.resize(size);
128✔
1877
        BfIterator it(buff, 0, width, width, 0);
128✔
1878
        for (size_t i = 0; i < size; ++i) {
2,506✔
1879
            uint64_t u_val = gen64() & bit_mask;
2,378✔
1880
            int64_t val = sign_extend_value(width, u_val);
2,378✔
1881
            values[i] = val;
2,378✔
1882
            it.set_value(val);
2,378✔
1883
            ++it;
2,378✔
1884
        }
2,378✔
1885
        it.move(0);
128✔
1886
        for (size_t i = 0; i < size; ++i) {
2,506✔
1887
            auto v = sign_extend_value(width, *it);
2,378✔
1888
            CHECK_EQUAL(v, values[i]);
2,378✔
1889
            ++it;
2,378✔
1890
        }
2,378✔
1891

1892
        std::sort(values.begin(), values.end());
128✔
1893
        auto last = std::unique(values.begin(), values.end());
128✔
1894
        for (auto val = values.begin(); val != last; val++) {
1,412✔
1895
            const auto mask = 1ULL << (width - 1);
1,284✔
1896
            const auto msb = populate(width, mask);
1,284✔
1897
            const auto search_vector = populate(width, *val);
1,284✔
1898

1899
            // perform the check with a normal iteration
1900
            size_t start = 0;
1,284✔
1901
            const auto end = size;
1,284✔
1902
            std::vector<size_t> linear_scan_result;
1,284✔
1903
            while (start < end) {
28,612✔
1904
                it.move(start);
27,328✔
1905
                const auto sv = sign_extend_value(width, *it);
27,328✔
1906
                if (sv == *val)
27,328✔
1907
                    linear_scan_result.push_back(start);
2,378✔
1908
                ++start;
27,328✔
1909
            }
27,328✔
1910

1911
            // Now use the optimized version
1912
            static auto vector_compare_eq = [](auto msb, auto a, auto b) {
7,866✔
1913
                return find_all_fields<Equal>(msb, a, b);
7,866✔
1914
            };
7,866✔
1915

1916
            start = 0;
1,284✔
1917
            std::vector<size_t> parallel_result;
1,284✔
1918
            while (start < end) {
4,818✔
1919
                start =
3,534✔
1920
                    parallel_subword_find(vector_compare_eq, buff, size_t{0}, width, msb, search_vector, start, end);
3,534✔
1921
                if (start != end)
3,534✔
1922
                    parallel_result.push_back(start);
2,378✔
1923
                start += 1;
3,534✔
1924
            }
3,534✔
1925

1926
            CHECK(!parallel_result.empty());
1,284✔
1927
            CHECK(!linear_scan_result.empty());
1,284✔
1928
            CHECK_EQUAL(linear_scan_result, parallel_result);
1,284✔
1929
        }
1,284✔
1930
    }
128✔
1931
}
2✔
1932

1933
TEST(ParallelSearchEqualNoMatch)
1934
{
2✔
1935
    uint64_t buff[2] = {0, 0};
2✔
1936
    constexpr size_t width = 2;
2✔
1937
    constexpr size_t size = 64;
2✔
1938
    constexpr int64_t key = 2;
2✔
1939
    BfIterator it(buff, 0, width, width, 0);
2✔
1940
    for (size_t i = 0; i < size; ++i) {
130✔
1941
        it.set_value(1);
128✔
1942
        ++it;
128✔
1943
    }
128✔
1944
    it.move(0);
2✔
1945
    for (size_t i = 0; i < size; ++i) {
130✔
1946
        auto v = sign_extend_value(width, *it);
128✔
1947
        CHECK_EQUAL(v, 1);
128✔
1948
        ++it;
128✔
1949
    }
128✔
1950
    const auto mask = 1ULL << (width - 1);
2✔
1951
    const auto msb = populate(width, mask);
2✔
1952
    const auto search_vector = populate(width, key);
2✔
1953

1954
    static auto vector_compare_eq = [](auto msb, auto a, auto b) {
4✔
1955
        return find_all_fields<Equal>(msb, a, b);
4✔
1956
    };
4✔
1957

1958
    size_t start = 0;
2✔
1959
    const auto end = size;
2✔
1960
    std::vector<size_t> parallel_result;
2✔
1961
    while (start < end) {
4✔
1962
        start = parallel_subword_find(vector_compare_eq, buff, size_t{0}, width, msb, search_vector, start, end);
2✔
1963
        if (start != end)
2✔
NEW
1964
            parallel_result.push_back(start);
×
1965
        start += 1;
2✔
1966
    }
2✔
1967

1968
    // perform the same check but with a normal iteration
1969
    start = 0;
2✔
1970
    std::vector<size_t> linear_scan_result;
2✔
1971
    while (start < end) {
130✔
1972
        it.move(start);
128✔
1973
        const auto sv = sign_extend_value(width, *it);
128✔
1974
        if (sv == key)
128✔
NEW
1975
            linear_scan_result.push_back(start);
×
1976
        ++start;
128✔
1977
    }
128✔
1978

1979
    CHECK(parallel_result.empty());
2✔
1980
    CHECK(linear_scan_result.empty());
2✔
1981
}
2✔
1982

1983
TEST(ParallelSearchNotEqual)
1984
{
2✔
1985
    uint64_t buff[2] = {0, 0};
2✔
1986
    constexpr size_t width = 2;
2✔
1987
    constexpr size_t size = 64;
2✔
1988
    constexpr int64_t key = 2;
2✔
1989
    BfIterator it(buff, 0, width, width, 0);
2✔
1990
    for (size_t i = 0; i < size; ++i) {
130✔
1991
        it.set_value(1);
128✔
1992
        ++it;
128✔
1993
    }
128✔
1994
    it.move(0);
2✔
1995
    for (size_t i = 0; i < size; ++i) {
130✔
1996
        auto v = sign_extend_value(width, *it);
128✔
1997
        CHECK_EQUAL(v, 1);
128✔
1998
        ++it;
128✔
1999
    }
128✔
2000
    const auto mask = 1ULL << (width - 1);
2✔
2001
    const auto msb = populate(width, mask);
2✔
2002
    const auto search_vector = populate(width, key);
2✔
2003

2004
    static auto vector_compare_neq = [](auto msb, auto a, auto b) {
128✔
2005
        return find_all_fields<NotEqual>(msb, a, b);
128✔
2006
    };
128✔
2007

2008
    size_t start = 0;
2✔
2009
    const auto end = size;
2✔
2010
    std::vector<size_t> parallel_result;
2✔
2011
    while (start < end) {
130✔
2012
        start = parallel_subword_find(vector_compare_neq, buff, size_t{0}, width, msb, search_vector, start, end);
128✔
2013
        if (start != end)
128✔
2014
            parallel_result.push_back(start);
128✔
2015
        start += 1;
128✔
2016
    }
128✔
2017

2018
    // perform the same check but with a normal iteration
2019
    start = 0;
2✔
2020
    std::vector<size_t> linear_scan_result;
2✔
2021
    while (start < end) {
130✔
2022
        it.move(start);
128✔
2023
        const auto sv = sign_extend_value(width, *it);
128✔
2024
        if (sv != key)
128✔
2025
            linear_scan_result.push_back(start);
128✔
2026
        ++start;
128✔
2027
    }
128✔
2028

2029
    CHECK(!parallel_result.empty());
2✔
2030
    CHECK(!linear_scan_result.empty());
2✔
2031
    CHECK_EQUAL(parallel_result, linear_scan_result);
2✔
2032
}
2✔
2033

2034
TEST(ParallelSearchLessThan)
2035
{
2✔
2036
    uint64_t buff[2] = {0, 0};
2✔
2037
    constexpr size_t width = 4;
2✔
2038
    constexpr size_t size = 32;
2✔
2039
    constexpr int64_t key = 3;
2✔
2040
    BfIterator it(buff, 0, width, width, 0);
2✔
2041
    for (size_t i = 0; i < size; ++i) {
66✔
2042
        it.set_value(2);
64✔
2043
        ++it;
64✔
2044
    }
64✔
2045
    it.move(0);
2✔
2046
    for (size_t i = 0; i < size; ++i) {
66✔
2047
        auto v = sign_extend_value(width, *it);
64✔
2048
        CHECK_EQUAL(v, 2);
64✔
2049
        ++it;
64✔
2050
    }
64✔
2051
    const auto mask = 1ULL << (width - 1);
2✔
2052
    const auto msb = populate(width, mask);
2✔
2053
    const auto search_vector = populate(width, key);
2✔
2054

2055
    static auto vector_compare_lt = [](auto msb, auto a, auto b) {
64✔
2056
        return find_all_fields<Less>(msb, a, b);
64✔
2057
    };
64✔
2058

2059
    size_t start = 0;
2✔
2060
    const auto end = size;
2✔
2061
    std::vector<size_t> parallel_result;
2✔
2062
    while (start < end) {
66✔
2063
        start = parallel_subword_find(vector_compare_lt, buff, size_t{0}, width, msb, search_vector, start, end);
64✔
2064
        if (start != end)
64✔
2065
            parallel_result.push_back(start);
64✔
2066
        start += 1;
64✔
2067
    }
64✔
2068

2069
    // perform the same check but with a normal iteration
2070
    start = 0;
2✔
2071
    std::vector<size_t> linear_scan_result;
2✔
2072
    while (start < end) {
66✔
2073
        it.move(start);
64✔
2074
        const auto sv = sign_extend_value(width, *it);
64✔
2075
        if (sv < key)
64✔
2076
            linear_scan_result.push_back(start);
64✔
2077
        ++start;
64✔
2078
    }
64✔
2079
    CHECK(!parallel_result.empty());
2✔
2080
    CHECK(!linear_scan_result.empty());
2✔
2081
    CHECK_EQUAL(parallel_result, linear_scan_result);
2✔
2082
}
2✔
2083

2084
TEST(ParallelSearchGreaterThan)
2085
{
2✔
2086
    uint64_t buff[2] = {0, 0};
2✔
2087
    constexpr size_t width = 4;
2✔
2088
    constexpr size_t size = 32;
2✔
2089
    constexpr int64_t key = 2;
2✔
2090
    BfIterator it(buff, 0, width, width, 0);
2✔
2091
    for (size_t i = 0; i < size; ++i) {
66✔
2092
        it.set_value(3);
64✔
2093
        ++it;
64✔
2094
    }
64✔
2095
    it.move(0);
2✔
2096
    for (size_t i = 0; i < size; ++i) {
66✔
2097
        auto v = sign_extend_value(width, *it);
64✔
2098
        CHECK_EQUAL(v, 3);
64✔
2099
        ++it;
64✔
2100
    }
64✔
2101
    const auto mask = 1ULL << (width - 1);
2✔
2102
    const auto msb = populate(width, mask);
2✔
2103
    const auto search_vector = populate(width, key);
2✔
2104

2105
    static auto vector_compare_gt = [](auto msb, auto a, auto b) {
64✔
2106
        return find_all_fields<Greater>(msb, a, b);
64✔
2107
    };
64✔
2108

2109
    size_t start = 0;
2✔
2110
    const auto end = size;
2✔
2111
    std::vector<size_t> parallel_result;
2✔
2112
    while (start < end) {
66✔
2113
        start = parallel_subword_find(vector_compare_gt, buff, size_t{0}, width, msb, search_vector, start, end);
64✔
2114
        if (start != end)
64✔
2115
            parallel_result.push_back(start);
64✔
2116
        start += 1;
64✔
2117
    }
64✔
2118

2119
    // perform the same check but with a normal iteration
2120
    start = 0;
2✔
2121
    std::vector<size_t> linear_scan_result;
2✔
2122
    while (start < end) {
66✔
2123
        it.move(start);
64✔
2124
        const auto sv = sign_extend_value(width, *it);
64✔
2125
        if (sv > key)
64✔
2126
            linear_scan_result.push_back(start);
64✔
2127
        ++start;
64✔
2128
    }
64✔
2129
    CHECK(!parallel_result.empty());
2✔
2130
    CHECK(!linear_scan_result.empty());
2✔
2131
    CHECK_EQUAL(parallel_result, linear_scan_result);
2✔
2132
}
2✔
2133

2134

2135
#endif // TEST_ARRAY
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc