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

realm / realm-core / github_pull_request_281750

30 Oct 2023 03:37PM UTC coverage: 90.528% (-1.0%) from 91.571%
github_pull_request_281750

Pull #6073

Evergreen

jedelbo
Log free space and history sizes when opening file
Pull Request #6073: Merge next-major

95488 of 175952 branches covered (0.0%)

8973 of 12277 new or added lines in 149 files covered. (73.09%)

622 existing lines in 51 files now uncovered.

233503 of 257934 relevant lines covered (90.53%)

6533720.56 hits per line

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

53.81
/src/realm/spec.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 <realm/impl/destroy_guard.hpp>
20
#include <realm/spec.hpp>
21
#include <realm/replication.hpp>
22
#include <realm/util/to_string.hpp>
23
#include <realm/group.hpp>
24
using namespace realm;
25

26
Spec::~Spec() noexcept {}
3,552✔
27

28
void Spec::detach() noexcept
29
{
5,431,593✔
30
    m_top.detach();
5,431,593✔
31
}
5,431,593✔
32

33
bool Spec::init(ref_type ref) noexcept
34
{
5,771,415✔
35
    MemRef mem(ref, get_alloc());
5,771,415✔
36
    init(mem);
5,771,415✔
37
    return true;
5,771,415✔
38
}
5,771,415✔
39

40
void Spec::init(MemRef mem) noexcept
41
{
5,769,108✔
42
    m_top.init_from_mem(mem);
5,769,108✔
43
    size_t top_size = m_top.size();
5,769,108✔
44
    REALM_ASSERT(top_size > s_attributes_ndx && top_size <= s_spec_max_size);
5,769,108✔
45

3,339,006✔
46
    m_types.init_from_ref(m_top.get_as_ref(s_types_ndx));
5,769,108✔
47
    m_names.init_from_ref(m_top.get_as_ref(s_names_ndx));
5,769,108✔
48
    m_attr.init_from_ref(m_top.get_as_ref(s_attributes_ndx));
5,769,108✔
49

3,339,006✔
50
    while (m_top.size() < s_spec_max_size) {
5,769,108✔
UNCOV
51
        m_top.add(0);
×
UNCOV
52
    }
×
53

3,339,006✔
54
    // Enumkeys array is only there when there are StringEnum columns
3,339,006✔
55
    if (auto ref = m_top.get_as_ref(s_enum_keys_ndx)) {
5,769,108✔
56
        m_enumkeys.init_from_ref(ref);
36✔
57
    }
36✔
58
    else {
5,769,072✔
59
        m_enumkeys.detach();
5,769,072✔
60
    }
5,769,072✔
61

3,339,006✔
62
    if (m_top.get_as_ref(s_col_keys_ndx) == 0) {
5,769,108✔
63
        // This is an upgrade - create column key array
UNCOV
64
        MemRef mem_ref = Array::create_empty_array(Array::type_Normal, false, m_top.get_alloc()); // Throws
×
UNCOV
65
        m_keys.init_from_mem(mem_ref);
×
UNCOV
66
        m_keys.update_parent();
×
UNCOV
67
        size_t num_cols = m_types.size();
×
UNCOV
68
        for (size_t i = 0; i < num_cols; i++) {
×
UNCOV
69
            m_keys.add(i);
×
UNCOV
70
        }
×
UNCOV
71
    }
×
72
    else {
5,769,108✔
73
        m_keys.init_from_parent();
5,769,108✔
74
    }
5,769,108✔
75

3,339,006✔
76

3,339,006✔
77
    update_internals();
5,769,108✔
78
}
5,769,108✔
79

80
void Spec::update_internals() noexcept
81
{
7,589,904✔
82
    m_num_public_columns = 0;
7,589,904✔
83
    size_t n = m_types.size();
7,589,904✔
84
    for (size_t i = 0; i < n; ++i) {
31,582,239✔
85
        if (ColumnType(int(m_types.get(i))) == col_type_BackLink) {
24,643,089✔
86
            // Now we have no more public columns
323,868✔
87
            return;
650,754✔
88
        }
650,754✔
89
        m_num_public_columns++;
23,992,335✔
90
    }
23,992,335✔
91
}
7,589,904✔
92

93
void Spec::update_from_parent() noexcept
94
{
810,879✔
95
    m_top.update_from_parent();
810,879✔
96
    m_types.update_from_parent();
810,879✔
97
    m_names.update_from_parent();
810,879✔
98
    m_attr.update_from_parent();
810,879✔
99

402,993✔
100
    if (m_top.get_as_ref(s_enum_keys_ndx) != 0) {
810,879✔
101
        m_enumkeys.update_from_parent();
18✔
102
    }
18✔
103
    else {
810,861✔
104
        m_enumkeys.detach();
810,861✔
105
    }
810,861✔
106

402,993✔
107
    m_keys.update_from_parent();
810,879✔
108

402,993✔
109
    update_internals();
810,879✔
110
}
810,879✔
111

112

113
MemRef Spec::create_empty_spec(Allocator& alloc)
114
{
339,375✔
115
    // The 'spec_set' contains the specification (types and names) of
168,267✔
116
    // all columns and sub-tables
168,267✔
117
    Array spec_set(alloc);
339,375✔
118
    _impl::DeepArrayDestroyGuard dg(&spec_set);
339,375✔
119
    spec_set.create(Array::type_HasRefs); // Throws
339,375✔
120

168,267✔
121
    _impl::DeepArrayRefDestroyGuard dg_2(alloc);
339,375✔
122
    {
339,375✔
123
        // One type for each column
168,267✔
124
        bool context_flag = false;
339,375✔
125
        MemRef mem = Array::create_empty_array(Array::type_Normal, context_flag, alloc); // Throws
339,375✔
126
        dg_2.reset(mem.get_ref());
339,375✔
127
        int_fast64_t v(from_ref(mem.get_ref()));
339,375✔
128
        spec_set.add(v); // Throws
339,375✔
129
        dg_2.release();
339,375✔
130
    }
339,375✔
131
    {
339,375✔
132
        size_t size = 0;
339,375✔
133
        // One name for each column
168,267✔
134
        MemRef mem = ArrayStringShort::create_array(size, alloc); // Throws
339,375✔
135
        dg_2.reset(mem.get_ref());
339,375✔
136
        int_fast64_t v = from_ref(mem.get_ref());
339,375✔
137
        spec_set.add(v); // Throws
339,375✔
138
        dg_2.release();
339,375✔
139
    }
339,375✔
140
    {
339,375✔
141
        // One attrib set for each column
168,267✔
142
        bool context_flag = false;
339,375✔
143
        MemRef mem = Array::create_empty_array(Array::type_Normal, context_flag, alloc); // Throws
339,375✔
144
        dg_2.reset(mem.get_ref());
339,375✔
145
        int_fast64_t v = from_ref(mem.get_ref());
339,375✔
146
        spec_set.add(v); // Throws
339,375✔
147
        dg_2.release();
339,375✔
148
    }
339,375✔
149
    spec_set.add(0); // Nested collections array
339,375✔
150
    spec_set.add(0); // Enumkeys array
339,375✔
151
    {
339,375✔
152
        // One key for each column
168,267✔
153
        bool context_flag = false;
339,375✔
154
        MemRef mem = Array::create_empty_array(Array::type_Normal, context_flag, alloc); // Throws
339,375✔
155
        dg_2.reset(mem.get_ref());
339,375✔
156
        int_fast64_t v = from_ref(mem.get_ref());
339,375✔
157
        spec_set.add(v); // Throws
339,375✔
158
        dg_2.release();
339,375✔
159
    }
339,375✔
160

168,267✔
161
    dg.release();
339,375✔
162
    return spec_set.get_mem();
339,375✔
163
}
339,375✔
164

165
ColKey Spec::update_colkey(ColKey existing_key, size_t spec_ndx, TableKey table_key)
UNCOV
166
{
×
UNCOV
167
    auto attr = get_column_attr(spec_ndx);
×
168
    // index and uniqueness are not passed on to the key, so clear them
UNCOV
169
    attr.reset(col_attr_Indexed);
×
UNCOV
170
    attr.reset(col_attr_Unique);
×
UNCOV
171
    auto type = get_column_type(spec_ndx);
×
UNCOV
172
    if (existing_key.get_type() != type || existing_key.get_attrs() != attr) {
×
UNCOV
173
        unsigned upper = unsigned(table_key.value);
×
174

UNCOV
175
        return ColKey(ColKey::Idx{existing_key.get_index().val}, type, attr, upper);
×
UNCOV
176
    }
×
177
    // Existing key is valid
UNCOV
178
    return existing_key;
×
UNCOV
179
}
×
180

181
bool Spec::convert_column_attributes()
UNCOV
182
{
×
UNCOV
183
    bool changes = false;
×
UNCOV
184
    size_t enumkey_ndx = 0;
×
185

UNCOV
186
    for (size_t column_ndx = 0; column_ndx < m_types.size(); column_ndx++) {
×
UNCOV
187
        if (column_ndx < m_names.size()) {
×
UNCOV
188
            StringData name = m_names.get(column_ndx);
×
UNCOV
189
            if (name.size() == 0) {
×
UNCOV
190
                auto new_name = std::string("col_") + util::to_string(column_ndx);
×
UNCOV
191
                m_names.set(column_ndx, new_name);
×
UNCOV
192
                changes = true;
×
UNCOV
193
            }
×
UNCOV
194
            else if (m_names.find_first(name) != column_ndx) {
×
UNCOV
195
                auto new_name = std::string(name.data()) + '_' + util::to_string(column_ndx);
×
UNCOV
196
                m_names.set(column_ndx, new_name);
×
UNCOV
197
                changes = true;
×
UNCOV
198
            }
×
UNCOV
199
        }
×
UNCOV
200
        ColumnType type = ColumnType(int(m_types.get(column_ndx)));
×
UNCOV
201
        ColumnAttrMask attr = ColumnAttrMask(m_attr.get(column_ndx));
×
UNCOV
202
        switch (type) {
×
UNCOV
203
            case col_type_Link:
×
UNCOV
204
                if (!attr.test(col_attr_Nullable)) {
×
UNCOV
205
                    attr.set(col_attr_Nullable);
×
UNCOV
206
                    m_attr.set(column_ndx, attr.m_value);
×
UNCOV
207
                    changes = true;
×
UNCOV
208
                }
×
UNCOV
209
                break;
×
UNCOV
210
            case col_type_LinkList:
×
UNCOV
211
                if (!attr.test(col_attr_List)) {
×
UNCOV
212
                    attr.set(col_attr_List);
×
UNCOV
213
                    m_attr.set(column_ndx, attr.m_value);
×
UNCOV
214
                    changes = true;
×
UNCOV
215
                }
×
UNCOV
216
                break;
×
UNCOV
217
            default:
×
UNCOV
218
                if (type == col_type_OldTable) {
×
UNCOV
219
                    Array subspecs(m_top.get_alloc());
×
UNCOV
220
                    subspecs.set_parent(&m_top, 3);
×
UNCOV
221
                    subspecs.init_from_parent();
×
222

UNCOV
223
                    Spec sub_spec(get_alloc());
×
UNCOV
224
                    size_t subspec_ndx = get_subspec_ndx(column_ndx);
×
UNCOV
225
                    ref_type ref = to_ref(subspecs.get(subspec_ndx)); // Throws
×
UNCOV
226
                    sub_spec.init(ref);
×
UNCOV
227
                    REALM_ASSERT(sub_spec.get_column_count() == 1);
×
UNCOV
228
                    m_types.set(column_ndx, int(sub_spec.get_column_type(0)));
×
UNCOV
229
                    m_attr.set(column_ndx, m_attr.get(column_ndx) | sub_spec.m_attr.get(0) | col_attr_List);
×
UNCOV
230
                    sub_spec.destroy();
×
231

UNCOV
232
                    subspecs.erase(subspec_ndx);
×
UNCOV
233
                    changes = true;
×
UNCOV
234
                }
×
UNCOV
235
                else if (type == col_type_OldStringEnum) {
×
UNCOV
236
                    m_types.set(column_ndx, int(col_type_String));
×
237
                    // We need to padd zeroes into the m_enumkeys so that the index in
238
                    // m_enumkeys matches the column index.
UNCOV
239
                    for (size_t i = enumkey_ndx; i < column_ndx; i++) {
×
UNCOV
240
                        m_enumkeys.insert(i, 0);
×
UNCOV
241
                    }
×
UNCOV
242
                    enumkey_ndx = column_ndx + 1;
×
UNCOV
243
                    changes = true;
×
UNCOV
244
                }
×
UNCOV
245
                else {
×
UNCOV
246
                    REALM_ASSERT_RELEASE(type.is_valid());
×
UNCOV
247
                }
×
UNCOV
248
                break;
×
UNCOV
249
        }
×
UNCOV
250
    }
×
UNCOV
251
    if (m_enumkeys.is_attached()) {
×
UNCOV
252
        while (m_enumkeys.size() < m_num_public_columns) {
×
UNCOV
253
            m_enumkeys.add(0);
×
UNCOV
254
        }
×
UNCOV
255
    }
×
UNCOV
256
    return changes;
×
UNCOV
257
}
×
258

259
bool Spec::convert_column_keys(TableKey table_key)
UNCOV
260
{
×
261
    // This step will ensure that the column keys has right attribute and type info
UNCOV
262
    bool changes = false;
×
UNCOV
263
    auto sz = m_types.size();
×
UNCOV
264
    for (size_t ndx = 0; ndx < sz; ndx++) {
×
UNCOV
265
        ColKey existing_key = ColKey{m_keys.get(ndx)};
×
UNCOV
266
        ColKey col_key = update_colkey(existing_key, ndx, table_key);
×
UNCOV
267
        if (col_key != existing_key) {
×
UNCOV
268
            m_keys.set(ndx, col_key.value);
×
UNCOV
269
            changes = true;
×
UNCOV
270
        }
×
UNCOV
271
    }
×
UNCOV
272
    return changes;
×
UNCOV
273
}
×
274

275
void Spec::fix_column_keys(TableKey table_key)
UNCOV
276
{
×
UNCOV
277
    if (get_column_name(m_num_public_columns - 1) == "!ROW_INDEX") {
×
UNCOV
278
        unsigned idx = unsigned(m_types.size()) - 1;
×
UNCOV
279
        size_t ndx = m_num_public_columns - 1;
×
280
        // Fixing "!ROW_INDEX" column
UNCOV
281
        {
×
UNCOV
282
            ColKey col_key(ColKey::Idx{idx}, col_type_Int, ColumnAttrMask(), table_key.value);
×
UNCOV
283
            m_keys.set(ndx, col_key.value);
×
UNCOV
284
        }
×
285
        // Fix backlink columns
UNCOV
286
        idx = unsigned(m_num_public_columns) - 1;
×
UNCOV
287
        for (ndx = m_num_public_columns; ndx < m_types.size(); ndx++, idx++) {
×
UNCOV
288
            ColKey col_key(ColKey::Idx{idx}, col_type_BackLink, ColumnAttrMask(), table_key.value);
×
UNCOV
289
            m_keys.set(ndx, col_key.value);
×
UNCOV
290
        }
×
UNCOV
291
    }
×
UNCOV
292
}
×
293

294
void Spec::insert_column(size_t column_ndx, ColKey col_key, ColumnType type, StringData name, int attr)
295
{
980,439✔
296
    REALM_ASSERT(column_ndx <= m_types.size());
980,439✔
297

483,243✔
298
    if (REALM_UNLIKELY(name.size() > Table::max_column_name_length)) {
980,439✔
299
        throw InvalidArgument(ErrorCodes::InvalidName, util::format("Name too long: %1", name));
18✔
300
    }
18✔
301
    if (get_column_index(name) != npos) {
980,421✔
302
        throw InvalidArgument(ErrorCodes::InvalidName, util::format("Property name in use: %1", name));
×
303
    }
×
304

483,234✔
305
    if (type != col_type_BackLink) {
980,421✔
306
        m_names.insert(column_ndx, name); // Throws
892,155✔
307
        m_num_public_columns++;
892,155✔
308
    }
892,155✔
309

483,234✔
310
    m_types.insert(column_ndx, int(type)); // Throws
980,421✔
311
    m_attr.insert(column_ndx, attr);       // Throws
980,421✔
312
    m_keys.insert(column_ndx, col_key.value);
980,421✔
313

483,234✔
314
    if (m_enumkeys.is_attached() && type != col_type_BackLink) {
980,421✔
315
        m_enumkeys.insert(column_ndx, 0);
12✔
316
    }
12✔
317

483,234✔
318
    update_internals();
980,421✔
319
}
980,421✔
320

321
void Spec::erase_column(size_t column_ndx)
322
{
18,717✔
323
    REALM_ASSERT(column_ndx < m_types.size());
18,717✔
324

8,925✔
325
    if (ColumnType(int(m_types.get(column_ndx))) != col_type_BackLink) {
18,717✔
326
        if (is_string_enum_type(column_ndx)) {
18,489✔
327
            // Enum columns do also have a separate key list
3✔
328
            ref_type keys_ref = m_enumkeys.get_as_ref(column_ndx);
6✔
329
            Array::destroy_deep(keys_ref, m_top.get_alloc());
6✔
330
            m_enumkeys.set(column_ndx, 0);
6✔
331
        }
6✔
332

8,814✔
333
        // Remove this column from the enum keys lookup and clean it up if it's now empty
8,814✔
334
        if (m_enumkeys.is_attached()) {
18,489✔
335
            m_enumkeys.erase(column_ndx); // Throws
18✔
336
            bool all_empty = true;
18✔
337
            for (size_t i = 0; i < m_enumkeys.size(); i++) {
30✔
338
                if (m_enumkeys.get(i) != 0) {
24✔
339
                    all_empty = false;
12✔
340
                    break;
12✔
341
                }
12✔
342
            }
24✔
343
            if (all_empty) {
18✔
344
                m_enumkeys.destroy_deep();
6✔
345
                m_top.set(4, 0);
6✔
346
            }
6✔
347
        }
18✔
348
        m_num_public_columns--;
18,489✔
349
        m_names.erase(column_ndx); // Throws
18,489✔
350
    }
18,489✔
351

8,925✔
352
    // Delete the entries common for all columns
8,925✔
353
    m_types.erase(column_ndx); // Throws
18,717✔
354
    m_attr.erase(column_ndx);  // Throws
18,717✔
355
    m_keys.erase(column_ndx);
18,717✔
356

8,925✔
357
    update_internals();
18,717✔
358
}
18,717✔
359

360
// For link and link list columns the old subspec array contain an entry which
361
// is the group-level table index of the target table, and for backlink
362
// columns the first entry is the group-level table index of the origin
363
// table, and the second entry is the index of the origin column in the
364
// origin table.
365
size_t Spec::get_subspec_ndx(size_t column_ndx) const noexcept
UNCOV
366
{
×
UNCOV
367
    REALM_ASSERT(column_ndx == get_column_count() || get_column_type(column_ndx) == col_type_Link ||
×
UNCOV
368
                 get_column_type(column_ndx) == col_type_LinkList ||
×
UNCOV
369
                 get_column_type(column_ndx) == col_type_BackLink ||
×
370
                 // col_type_OldTable is used when migrating from file format 9 to 10.
UNCOV
371
                 get_column_type(column_ndx) == col_type_OldTable);
×
372

UNCOV
373
    size_t subspec_ndx = 0;
×
UNCOV
374
    for (size_t i = 0; i != column_ndx; ++i) {
×
UNCOV
375
        ColumnType type = ColumnType(int(m_types.get(i)));
×
UNCOV
376
        if (type == col_type_Link || type == col_type_LinkList) {
×
UNCOV
377
            subspec_ndx += 1; // index of dest column
×
UNCOV
378
        }
×
UNCOV
379
        else if (type == col_type_BackLink) {
×
UNCOV
380
            subspec_ndx += 2; // index of table and index of linked column
×
UNCOV
381
        }
×
UNCOV
382
    }
×
UNCOV
383
    return subspec_ndx;
×
UNCOV
384
}
×
385

386

387
void Spec::upgrade_string_to_enum(size_t column_ndx, ref_type keys_ref)
388
{
690✔
389
    REALM_ASSERT(get_column_type(column_ndx) == col_type_String);
690✔
390

345✔
391
    // Create the enumkeys list if needed
345✔
392
    if (!m_enumkeys.is_attached()) {
690✔
393
        m_enumkeys.create(Array::type_HasRefs, false, m_num_public_columns);
654✔
394
        m_top.set(4, m_enumkeys.get_ref());
654✔
395
        m_enumkeys.set_parent(&m_top, 4);
654✔
396
    }
654✔
397

345✔
398
    // Insert the new key list
345✔
399
    m_enumkeys.set(column_ndx, keys_ref);
690✔
400
}
690✔
401

402
bool Spec::is_string_enum_type(size_t column_ndx) const noexcept
403
{
5,558,967✔
404
    return m_enumkeys.is_attached() ? (m_enumkeys.get(column_ndx) != 0) : false;
5,021,010✔
405
}
5,558,967✔
406

407
ref_type Spec::get_enumkeys_ref(size_t column_ndx, ArrayParent*& keys_parent) noexcept
408
{
3,709,137✔
409
    // We also need to return parent info
1,853,208✔
410
    keys_parent = &m_enumkeys;
3,709,137✔
411

1,853,208✔
412
    return m_enumkeys.get_as_ref(column_ndx);
3,709,137✔
413
}
3,709,137✔
414

415
namespace {
416

417
template <class T>
418
bool compare(const T& a, const T& b)
419
{
×
420
    if (a.size() != b.size())
×
421
        return false;
×
422

423
    for (size_t i = 0; i < a.size(); ++i) {
×
424
        if (b.get(i) != a.get(i))
×
425
            return false;
×
426
    }
×
427

428
    return true;
×
429
}
×
430

431
} // namespace
432

433
bool Spec::operator==(const Spec& spec) const noexcept
434
{
×
435
    if (!compare(m_attr, spec.m_attr))
×
436
        return false;
×
437
    if (!m_names.compare_string(spec.m_names))
×
438
        return false;
×
439

440
    // check each column's type
441
    const size_t column_count = get_column_count();
×
442
    for (size_t col_ndx = 0; col_ndx < column_count; ++col_ndx) {
×
443
        ColumnType col_type = ColumnType(int(m_types.get(col_ndx)));
×
444
        switch (col_type) {
×
445
            case col_type_Link:
×
446
            case col_type_TypedLink:
×
447
            case col_type_LinkList: {
×
448
                // In addition to name and attributes, the link target table must also be compared
449
                REALM_ASSERT(false); // We can no longer compare specs - in fact we don't want to
×
UNCOV
450
                break;
×
UNCOV
451
            }
×
452
            case col_type_Int:
×
453
            case col_type_Bool:
×
454
            case col_type_Binary:
×
455
            case col_type_String:
×
456
            case col_type_Mixed:
×
457
            case col_type_Timestamp:
×
458
            case col_type_Float:
×
459
            case col_type_Double:
×
460
            case col_type_Decimal:
×
461
            case col_type_BackLink:
×
462
            case col_type_ObjectId:
×
463
            case col_type_UUID:
×
464
                // All other column types are compared as before
465
                if (m_types.get(col_ndx) != spec.m_types.get(col_ndx))
×
466
                    return false;
×
467
                break;
×
468
        }
×
469
    }
×
470

471
    return true;
×
472
}
×
473

474

475
ColKey Spec::get_key(size_t column_ndx) const
476
{
72,550,563✔
477
    auto key = ColKey(m_keys.get(column_ndx));
72,550,563✔
478
    REALM_ASSERT(key.get_type().is_valid());
72,550,563✔
479
    return key;
72,550,563✔
480
}
72,550,563✔
481

482
void Spec::verify() const
483
{
2,935,965✔
484
#ifdef REALM_DEBUG
2,935,965✔
485
    REALM_ASSERT(m_names.size() == get_public_column_count());
2,935,965✔
486
    REALM_ASSERT(m_types.size() == get_column_count());
2,935,965✔
487
    REALM_ASSERT(m_attr.size() == get_column_count());
2,935,965✔
488

1,481,073✔
489
    REALM_ASSERT(m_types.get_ref() == m_top.get_as_ref(0));
2,935,965✔
490
    REALM_ASSERT(m_names.get_ref() == m_top.get_as_ref(1));
2,935,965✔
491
    REALM_ASSERT(m_attr.get_ref() == m_top.get_as_ref(2));
2,935,965✔
492
#endif
2,935,965✔
493
}
2,935,965✔
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