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

realm / realm-core / 2314

13 May 2024 08:25AM UTC coverage: 90.8% (-0.009%) from 90.809%
2314

push

Evergreen

web-flow
[bindgen] Adding a `app_user_as_sync_user` helper (#7684)

* Adding app_user_as_sync_user

* Update CHANGELOG.md

Co-authored-by: Kenneth Geisshirt <kenneth.geisshirt@mongodb.com>

---------

Co-authored-by: Kenneth Geisshirt <kenneth.geisshirt@mongodb.com>

102052 of 181070 branches covered (56.36%)

214528 of 236265 relevant lines covered (90.8%)

5699202.49 hits per line

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

74.12
/test/test_all.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
// #define USE_VLD
20
#if defined(_MSC_VER) && defined(_DEBUG) && defined(USE_VLD)
21
#include "C:\\Program Files (x86)\\Visual Leak Detector\\include\\vld.h"
22
#endif
23

24
#include <ctime>
25
#include <cstring>
26
#include <cstdlib>
27
#include <algorithm>
28
#include <stdexcept>
29
#include <tuple>
30
#include <memory>
31
#include <iterator>
32
#include <vector>
33
#include <locale>
34
#include <sstream>
35
#include <fstream>
36
#include <iostream>
37
#include <iomanip>
38
#include <thread>
39

40
#include <realm/util/features.h>
41
#include <realm/util/platform_info.hpp>
42
#include <realm.hpp>
43
#include <realm/utilities.hpp>
44
#include <realm/disable_sync_to_disk.hpp>
45

46
#include "util/timer.hpp"
47
#include "util/resource_limits.hpp"
48

49
#include "test.hpp"
50
#include "test_all.hpp"
51

52
#ifdef _WIN32
53
#include <Windows.h>
54
#if REALM_UWP
55
#include <winrt/Windows.ApplicationModel.h>
56
#include <winrt/Windows.Storage.h>
57
#else
58
// PathCchRemoveFileSpec()
59
#include <pathcch.h>
60
#pragma comment(lib, "Pathcch.lib")
61
#endif
62
#endif
63

64
// Need to disable file descriptor leak checks on Apple platforms, as it seems
65
// like an unknown number of file descriptors can be left behind, presumably due
66
// the way asynchronous DNS lookup is implemented.
67
#if !defined _WIN32 && !REALM_PLATFORM_APPLE
68
#define ENABLE_FILE_DESCRIPTOR_LEAK_CHECK
69
#endif
70

71
#ifdef ENABLE_FILE_DESCRIPTOR_LEAK_CHECK
72
#include <unistd.h>
73
#include <fcntl.h>
74
#endif
75

76
using namespace realm;
77
using namespace realm::test_util;
78
using namespace realm::test_util::unit_test;
79

80
// Random seed for various random number generators used by fuzzying unit tests.
81
unsigned int unit_test_random_seed;
82

83
namespace {
84

85
// clang-format off
86
const char* file_order[] = {
87
    // When choosing order, please try to use these guidelines:
88
    //
89
    //  - If feature A depends on feature B, test feature B first.
90
    //
91
    //  - If feature A has a more central role in the API than feature B, test
92
    //    feature A first.
93
    //
94
    "test_self.cpp",
95

96
    // realm/util/
97
    "test_safe_int_ops.cpp",
98
    "test_basic_utils.cpp",
99
    "test_file*.cpp",
100
    "test_thread.cpp",
101
    "test_util_network.cpp",
102
    "test_utf8.cpp",
103

104
    // /realm/ (helpers)
105
    "test_string_data.cpp",
106
    "test_binary_data.cpp",
107

108
    // /realm/impl/ (detail)
109
    "test_alloc*.cpp",
110
    "test_array*.cpp",
111
    "test_column*.cpp",
112
    "test_index*.cpp",
113
    "test_destroy_guard.cpp",
114

115
    // /realm/ (main API)
116
    "test_table*.cpp",
117
    "test_descriptor*.cpp",
118
    "test_group*.cpp",
119
    "test_shared*.cpp",
120
    "test_transactions*.cpp",
121
    "test_query*.cpp",
122
    "test_links.cpp",
123
    "test_link_query_view.cpp",
124
    "test_json.cpp",
125
    "test_replication*.cpp",
126

127
    "test_lang_bind_helper.cpp",
128

129
    "large_tests*.cpp",
130
    "test_crypto.cpp",
131
    "test_transform_collections_mixed.cpp",
132
    "test_transform.cpp",
133
    "test_array.cpp",
134
    "test_lang_bind_helper_sync.cpp",
135
    "test_sync.cpp",
136
    "test_backup.cpp",
137
    "test_sync_fuzz.cpp"
138
};
139
// clang-format on
140

141
void fix_max_open_files()
142
{
8✔
143
    if (system_has_rlimit(resource_NumOpenFiles)) {
8✔
144
        long soft_limit = get_soft_rlimit(resource_NumOpenFiles);
8✔
145
        if (soft_limit >= 0) {
8✔
146
            long hard_limit = get_hard_rlimit(resource_NumOpenFiles);
8✔
147
            long new_soft_limit = hard_limit < 0 ? 4096 : hard_limit;
8✔
148
            if (new_soft_limit > soft_limit) {
8✔
149
                set_soft_rlimit(resource_NumOpenFiles, new_soft_limit);
×
150
                /*
151
                std::cout << "\n"
152
                    "MaxOpenFiles: "<<soft_limit<<" --> "<<new_soft_limit<<"\n";
153
                */
154
            }
×
155
        }
8✔
156
    }
8✔
157
}
8✔
158

159

160
long get_num_open_files()
161
{
12✔
162
#ifdef ENABLE_FILE_DESCRIPTOR_LEAK_CHECK
8✔
163
    if (system_has_rlimit(resource_NumOpenFiles)) {
8✔
164
        long soft_limit = get_soft_rlimit(resource_NumOpenFiles);
8✔
165
        if (soft_limit >= 0) {
8✔
166
            long num_open_files = 0;
8✔
167
            for (long i = 0; i < soft_limit; ++i) {
512,008✔
168
                int fildes = int(i);
512,000✔
169
                int ret = fcntl(fildes, F_GETFD);
512,000✔
170
                if (ret != -1) {
512,000✔
171
                    ++num_open_files;
32✔
172
                    continue;
32✔
173
                }
32✔
174
                if (errno != EBADF)
511,968✔
175
                    throw std::runtime_error("fcntl() failed");
176
            }
511,968✔
177
            return num_open_files;
8✔
178
        }
8✔
179
    }
8✔
180
#endif
181
    return -1;
4✔
182
}
12✔
183

184
void set_random_seed()
185
{
8✔
186
    // Select random seed for the random generator that some of our unit tests are using
187
    const char* str = getenv("UNITTEST_RANDOM_SEED");
8✔
188
    if (str && strlen(str) != 0 && strcmp(str, "random") != 0) {
8!
189
        std::istringstream in(str);
×
190
        in.imbue(std::locale::classic());
×
191
        in.flags(in.flags() & ~std::ios_base::skipws); // Do not accept white space
×
192
        in >> unit_test_random_seed;
×
193
        bool bad = !in || in.get() != std::char_traits<char>::eof();
×
194
        if (bad)
×
195
            throw std::runtime_error("Bad random seed");
×
196
    }
×
197
    else {
8✔
198
        unit_test_random_seed = produce_nondeterministic_random_seed();
8✔
199
    }
8✔
200
    random_seed(unit_test_random_seed);
8✔
201
}
8✔
202

203
class AggressiveGovernor : public util::PageReclaimGovernor {
204
public:
205
    util::UniqueFunction<int64_t()> current_target_getter(size_t) override
206
    {
×
207
        return []() {
×
208
            return 4096;
×
209
        };
×
210
    }
×
211
    void report_target_result(int64_t) override {}
×
212
};
213

214
AggressiveGovernor aggressive_governor;
215

216
void set_always_encrypt()
217
{
8✔
218
    if (const char* env = getenv("UNITTEST_ENCRYPT_ALL")) {
8✔
219
        std::string str(env);
8✔
220
        for (auto& c : str) {
8✔
221
            c = tolower(c);
8✔
222
        }
8✔
223
        if (str == "1" || str == "on" || str == "yes") {
8✔
224
            enable_always_encrypt();
×
225
            // ask for a very aggressive page reclaimer to maximize chance of triggering a bug.
226
            realm::util::set_page_reclaim_governor(&aggressive_governor);
×
227
        }
×
228
    }
8✔
229
}
8✔
230

231
void display_build_config()
232
{
8✔
233
    const char* with_debug = Version::has_feature(feature_Debug) ? "Enabled" : "Disabled";
8✔
234

235
#if REALM_ENABLE_MEMDEBUG
236
    const char* memdebug = "Enabled";
237
#else
238
    const char* memdebug = "Disabled";
8✔
239
#endif
8✔
240

241
#if REALM_ENABLE_ENCRYPTION
8✔
242
    bool always_encrypt = is_always_encrypt_enabled();
8✔
243
    const char* encryption = always_encrypt ? "Enabled at compile-time (always encrypt = yes)"
8✔
244
                                            : "Enabled at compile-time (always encrypt = no)";
8✔
245
#else
246
    const char* encryption = "Disabled at compile-time";
247
#endif
248

249
#ifdef REALM_COMPILER_SSE
4✔
250
    const char* compiler_sse = "Yes";
4✔
251
#else
252
    const char* compiler_sse = "No";
4✔
253
#endif
4✔
254

255
#ifdef REALM_COMPILER_AVX
4✔
256
    const char* compiler_avx = "Yes";
4✔
257
#else
258
    const char* compiler_avx = "No";
4✔
259
#endif
4✔
260

261
    const char* cpu_sse = realm::sseavx<42>() ? "4.2" : (realm::sseavx<30>() ? "3.0" : "None");
8✔
262

263
    const char* cpu_avx = realm::sseavx<1>() ? "Yes" : "No";
8✔
264

265
    std::cout << std::endl
8✔
266
              << "Realm version: " << Version::get_version() << " with Debug " << with_debug << "\n"
8✔
267
              << "Platform: " << util::get_platform_info() << "\n"
8✔
268
              << "Encryption: " << encryption << "\n"
8✔
269
              << "\n"
8✔
270
              << "REALM_MAX_BPNODE_SIZE = " << REALM_MAX_BPNODE_SIZE << "\n"
8✔
271
              << "REALM_MEMDEBUG = " << memdebug << "\n"
8✔
272
              << "\n"
8✔
273
              // Be aware that ps3/xbox have sizeof (void*) = 4 && sizeof (size_t) == 8
274
              // We decide to print size_t here
275
              << "sizeof (size_t) * 8 = " << (sizeof(size_t) * 8) << "\n"
8✔
276
              << "\n"
8✔
277
              << "Compiler supported SSE (auto detect):       " << compiler_sse << "\n"
8✔
278
              << "This CPU supports SSE (auto detect):        " << cpu_sse << "\n"
8✔
279
              << "Compiler supported AVX (auto detect):       " << compiler_avx << "\n"
8✔
280
              << "This CPU supports AVX (AVX1) (auto detect): " << cpu_avx << "\n"
8✔
281
              << "\n"
8✔
282
              << "UNITTEST_RANDOM_SEED:                       " << unit_test_random_seed << "\n"
8✔
283
              << "Test path prefix:                           " << test_util::get_test_path_prefix() << "\n"
8✔
284
              << "Test resource path:                         " << test_util::get_test_resource_path() << "\n"
8✔
285
              << std::endl;
8✔
286
}
8✔
287

288

289
// Records elapsed time for each test and shows a "Top 5" at the end.
290
class CustomReporter : public SimpleReporter {
291
public:
292
    explicit CustomReporter(bool report_progress)
293
        : SimpleReporter(report_progress)
4✔
294
    {
8✔
295
    }
8✔
296

297
    ~CustomReporter() noexcept {}
8✔
298

299
    void end(const TestContext& context, double elapsed_seconds) override
300
    {
8,354✔
301
        result r;
8,354✔
302
        r.test_index = context.test_index;
8,354✔
303
        r.recurrence_index = context.recurrence_index;
8,354✔
304
        r.elapsed_seconds = elapsed_seconds;
8,354✔
305
        m_results.push_back(r);
8,354✔
306
        SimpleReporter::end(context, elapsed_seconds);
8,354✔
307
    }
8,354✔
308

309
    void summary(const SharedContext& context, const Summary& results_summary) override
310
    {
8✔
311
        SimpleReporter::summary(context, results_summary);
8✔
312

313
        size_t max_n = 5;
8✔
314
        size_t n = std::min<size_t>(max_n, m_results.size());
8✔
315
        if (n < 2)
8✔
316
            return;
×
317

318
        partial_sort(m_results.begin(), m_results.begin() + n, m_results.end());
8✔
319
        std::vector<std::tuple<std::string, std::string>> rows;
8✔
320
        size_t name_col_width = 0, time_col_width = 0;
8✔
321
        for (size_t i = 0; i < n; ++i) {
48✔
322
            const result& r = m_results[i];
40✔
323
            const TestDetails& details = context.test_list.get_test_details(r.test_index);
40✔
324
            std::ostringstream out;
40✔
325
            out.imbue(std::locale::classic());
40✔
326
            out << details.test_name;
40✔
327
            if (context.num_recurrences > 1)
40✔
328
                out << '#' << (r.recurrence_index + 1);
×
329
            std::string name = out.str();
40✔
330
            std::string time = Timer::format(r.elapsed_seconds);
40✔
331
            rows.emplace_back(name, time);
40✔
332
            if (name.size() > name_col_width)
40✔
333
                name_col_width = name.size();
12✔
334
            if (time.size() > time_col_width)
40✔
335
                time_col_width = time.size();
8✔
336
        }
40✔
337

338
        name_col_width += 2;
8✔
339
        size_t full_width = name_col_width + time_col_width;
8✔
340
        std::cout.fill('-');
8✔
341
        std::cout << "\nTop " << n << " time usage:\n"
8✔
342
                  << std::setw(int(full_width)) << ""
8✔
343
                  << "\n";
8✔
344
        std::cout.fill(' ');
8✔
345
        for (const auto& row : rows) {
40✔
346
            std::cout << std::left << std::setw(int(name_col_width)) << std::get<0>(row) << std::right
40✔
347
                      << std::setw(int(time_col_width)) << std::get<1>(row) << "\n";
40✔
348
        }
40✔
349
    }
8✔
350

351
private:
352
    struct result {
353
        size_t test_index;
354
        int recurrence_index;
355
        double elapsed_seconds;
356
        bool operator<(const result& r) const
357
        {
9,658✔
358
            return elapsed_seconds > r.elapsed_seconds; // Descending order
9,658✔
359
        }
9,658✔
360
    };
361

362
    std::vector<result> m_results;
363
};
364

365

366
void put_time(std::ostream& out, const std::tm& tm, const char* format)
367
{
×
368
    const std::time_put<char>& facet = std::use_facet<std::time_put<char>>(out.getloc());
×
369
    facet.put(std::ostreambuf_iterator<char>(out), out, ' ', &tm, format, format + strlen(format));
×
370
}
×
371

372

373
bool run_tests(const std::shared_ptr<realm::util::Logger>& logger = nullptr)
374
{
8✔
375
    {
8✔
376
        const char* str = getenv("UNITTEST_KEEP_FILES");
8✔
377
        if (str && strlen(str) != 0)
8!
378
            keep_test_files();
×
379
    }
8✔
380
    const bool running_spawned_process = getenv("REALM_SPAWNED");
8✔
381

382
    TestList::Config config;
8✔
383
    config.logger = logger;
8✔
384

385
    // Log timestamps
386
    {
8✔
387
        const char* str = getenv("UNITTEST_LOG_TIMESTAMPS");
8✔
388
        if (str && std::strlen(str) != 0)
8!
389
            config.log_timestamps = true;
×
390
    }
8✔
391

392
    // Set number of threads
393
    {
8✔
394
        const char* str = getenv("UNITTEST_THREADS");
8✔
395
        if (str && strlen(str) != 0) {
8!
396
            std::istringstream in(str);
×
397
            in.imbue(std::locale::classic());
×
398
            in.flags(in.flags() & ~std::ios_base::skipws); // Do not accept white space
×
399
            in >> config.num_threads;
×
400
            bool bad = !in || in.get() != std::char_traits<char>::eof() || config.num_threads < 1;
×
401
            if (bad)
×
402
                throw std::runtime_error("Bad number of threads");
×
403
            if (config.num_threads > 1 && !running_spawned_process)
×
404
                std::cout << "Number of test threads: " << config.num_threads << "\n\n";
×
405
        }
×
406
        else {
8✔
407
            config.num_threads = std::thread::hardware_concurrency();
8✔
408
            if (!running_spawned_process) {
8✔
409
                std::cout << "Number of test threads: " << config.num_threads << " (default)\n";
8✔
410
                std::cout << "(Use UNITTEST_THREADS=1 to serialize testing) \n\n";
8✔
411
            }
8✔
412
        }
8✔
413
    }
8✔
414

415
    // Set number of repetitions
416
    {
8✔
417
        const char* str = getenv("UNITTEST_REPEAT");
8✔
418
        if (str && strlen(str) != 0) {
8!
419
            std::istringstream in(str);
×
420
            in.imbue(std::locale::classic());
×
421
            in.flags(in.flags() & ~std::ios_base::skipws); // Do not accept white space
×
422
            in >> config.num_repetitions;
×
423
            bool bad = !in || in.get() != std::char_traits<char>::eof() || config.num_repetitions < 0;
×
424
            if (bad)
×
425
                throw std::runtime_error("Bad number of repetitions");
×
426
        }
×
427
    }
8✔
428

429
    // Shuffle
430
    {
8✔
431
        const char* str = getenv("UNITTEST_SHUFFLE");
8✔
432
        if (config.num_threads > 1 || (str && strlen(str) != 0))
8!
433
            config.shuffle = true;
8✔
434
    }
8✔
435

436
    // Set up reporter
437
    util::File junit_file;
8✔
438
    util::File::Streambuf junit_streambuf(&junit_file);
8✔
439
    std::ostream junit_out(&junit_streambuf);
8✔
440
    std::vector<std::unique_ptr<Reporter>> reporters;
8✔
441
    {
8✔
442
        const char* str = getenv("UNITTEST_PROGRESS");
8✔
443
        bool report_progress = str && strlen(str) != 0;
8✔
444
        reporters.push_back(std::make_unique<CustomReporter>(report_progress));
8✔
445
    }
8✔
446
    if (const char* str = getenv("UNITTEST_XML"); str && strlen(str) != 0) {
8!
447
        std::cout << "Configuring jUnit reporter to store test results in " << str << std::endl;
×
448
        junit_file.open(str, util::File::mode_Write);
×
449
        const char* test_suite_name = getenv("UNITTEST_SUITE_NAME");
×
450
        if (!test_suite_name || !strlen(test_suite_name))
×
451
            test_suite_name = "realm-core-tests";
×
452
        reporters.push_back(create_junit_reporter(junit_out, test_suite_name));
×
453
    }
×
454
    else if (const char* str = getenv("UNITTEST_EVERGREEN_TEST_RESULTS"); str && strlen(str) != 0) {
8✔
455
        std::cout << "Configuring evergreen reporter to store test results in " << str << std::endl;
8✔
456
        reporters.push_back(create_evergreen_reporter(str));
8✔
457
    }
8✔
458
    auto reporter = create_combined_reporter(reporters);
8✔
459
    config.reporter = reporter.get();
8✔
460

461
    // Set up filter
462
    const char* filter_str = getenv("UNITTEST_FILTER");
8✔
463
    const char* test_only = get_test_only();
8✔
464
    if (test_only)
8✔
465
        filter_str = test_only;
×
466
    std::unique_ptr<Filter> filter;
8✔
467
    if (filter_str && strlen(filter_str) != 0)
8!
468
        filter = create_wildcard_filter(filter_str);
×
469
    config.filter = filter.get();
8✔
470

471
    // Set intra test log level threshold
472
    {
8✔
473
        const char* str = getenv("UNITTEST_LOG_LEVEL");
8✔
474
        if (str && strlen(str) != 0) {
8!
475
            std::istringstream in(str);
×
476
            in.imbue(std::locale::classic());
×
477
            in.flags(in.flags() & ~std::ios_base::skipws); // Do not accept white space
×
478
            in >> config.intra_test_log_level;
×
479
            bool bad = !in || in.get() != std::char_traits<char>::eof();
×
480
            if (bad)
×
481
                throw std::runtime_error("Bad intra test log level");
×
482
        }
×
483
    }
8✔
484

485
    // Set up per-thread file logging
486
    {
8✔
487
        const char* str = getenv("UNITTEST_LOG_TO_FILES");
8✔
488
        if (str && strlen(str) != 0) {
8!
489
            std::ostringstream out;
×
490
            out.imbue(std::locale::classic());
×
491
            time_t now = time(nullptr);
×
492
            tm tm = *localtime(&now);
×
493
            out << "test_logs_";
×
494
            put_time(out, tm, "%Y%m%d_%H%M%S");
×
495
            std::string dir_path = get_test_path_prefix() + out.str();
×
496
            util::make_dir(dir_path);
×
497
            config.per_thread_log_path = util::File::resolve("thread_%.log", dir_path);
×
498
        }
×
499
    }
8✔
500

501
    // Enable abort on failure
502
    {
8✔
503
        const char* str = getenv("UNITTEST_ABORT_ON_FAILURE");
8✔
504
        if (str && strlen(str) != 0) {
8!
505
            config.abort_on_failure = true;
×
506
        }
×
507
    }
8✔
508

509
    // Run
510
    TestList& list = get_default_test_list();
8✔
511
    list.sort(PatternBasedFileOrder(file_order));
8✔
512
    bool success = list.run(config);
8✔
513

514
    if (test_only)
8✔
515
        std::cout << "\n*** BE AWARE THAT MOST TESTS WERE EXCLUDED DUE TO USING 'ONLY' MACRO ***\n";
×
516

517
    std::cout << "\n";
8✔
518

519
    // The iOS Simulator has a separate set of kernel file caches from the parent
520
    // OS, and if the simulator is deleted immediately after running the tests
521
    // (as is done on CI), the writes never actually make it to disk without
522
    // an explicit F_FULLFSYNC.
523
    if (junit_file.is_attached()) {
8✔
524
        junit_out.flush();
×
525
        junit_file.sync();
×
526
    }
×
527

528
    return success;
8✔
529
}
8✔
530

531
} // anonymous namespace
532

533

534
int test_all(const std::shared_ptr<realm::util::Logger>& logger)
535
{
8✔
536
    // General note: Some Github clients on Windows will interfere with the .realm files created by unit tests (the
537
    // git client will attempt to access the files when it sees that new files have been created). This may cause
538
    // very rare/sporadic segfaults and asserts. If the temporary directory path is outside revision control, there
539
    // is no problem. Otherwise we need two things fulfilled: 1) The directory must be in .gitignore, and also 2)
540
    // The directory must be newly created and not added to git.
541

542
    // Disable buffering on std::cout so that progress messages can be related to
543
    // error messages.
544
    std::cout.setf(std::ios::unitbuf);
8✔
545

546
#ifndef REALM_COVER
8✔
547
    // No need to synchronize file changes to physical medium in the test suite,
548
    // as that would only make a difference if the entire system crashes,
549
    // e.g. due to power off.
550
    // NOTE: This is not strictly true. If encryption is enabled, a crash of the testsuite
551
    // (not the whole platform) may produce corrupt realm files.
552
    char* enable_sync_to_disk = getenv("UNITTEST_ENABLE_SYNC_TO_DISK");
8✔
553
    if (!enable_sync_to_disk)
8✔
554
        disable_sync_to_disk();
8✔
555
#endif
8✔
556

557
    char* no_error_exitcode_str = getenv("UNITTEST_NO_ERROR_EXITCODE");
8✔
558
    bool no_error_exit_status = no_error_exitcode_str && strlen(no_error_exitcode_str) != 0;
8!
559

560
#ifdef WIN32
561
#if REALM_UWP
562
    std::string path =
563
        winrt::to_string(winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path());
564
    path += "\\TestAssets\\";
565
    set_test_resource_path(path);
566
    set_test_path_prefix(path);
567
#endif
568
#endif
569

570
    set_random_seed();
8✔
571
    set_always_encrypt();
8✔
572

573
    fix_max_open_files();
8✔
574

575
    if (!getenv("REALM_SPAWNED"))
8✔
576
        display_build_config();
8✔
577

578
    long num_open_files = get_num_open_files();
8✔
579

580
    bool success = run_tests(logger);
8✔
581

582
    if (num_open_files >= 0) {
8✔
583
        long num_open_files_2 = get_num_open_files();
4✔
584
        REALM_ASSERT(num_open_files_2 >= 0);
4✔
585
        if (num_open_files_2 > num_open_files) {
4✔
586
            long n = num_open_files_2 - num_open_files;
×
587
            // FIXME: This should be an error, but OpenSSL seems to open
588
            // files behind our back, and calling OPENSSL_cleanup() does not
589
            // seem to have any effect.
590
            std::cerr << "WARNING: " << n << " file descriptors were leaked\n";
×
591
            // success = false;
592
        }
×
593
    }
4✔
594

595
#ifdef _MSC_VER
596
    // We don't want spawned processes (see spawned_process.hpp to require user interaction).
597
    if (!getenv("REALM_SPAWNED"))
598
        getchar(); // wait for key
599
#endif
600

601
    return success || no_error_exit_status ? EXIT_SUCCESS : EXIT_FAILURE;
8!
602
}
8✔
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