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

realm / realm-core / 2214

10 Apr 2024 11:21PM UTC coverage: 91.813% (-0.8%) from 92.623%
2214

push

Evergreen

web-flow
Add missing availability checks for SecCopyErrorMessageString (#7577)

This requires iOS 11.3 and we currently target iOS 11.

94848 of 175770 branches covered (53.96%)

7 of 22 new or added lines in 2 files covered. (31.82%)

1815 existing lines in 77 files now uncovered.

242945 of 264608 relevant lines covered (91.81%)

6136478.37 hits per line

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

98.96
/test/object-store/sync/sync_manager.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 <util/event_loop.hpp>
20
#include <util/test_path.hpp>
21
#include <util/test_utils.hpp>
22
#include <util/sync/session_util.hpp>
23
#include <util/sync/sync_test_utils.hpp>
24

25
#include <realm/object-store/property.hpp>
26
#include <realm/object-store/sync/sync_manager.hpp>
27
#include <realm/object-store/sync/sync_user.hpp>
28

29
#include <realm/sync/config.hpp>
30

31
#include <realm/util/logger.hpp>
32
#include <realm/util/optional.hpp>
33
#include <realm/util/scope_exit.hpp>
34

35
using namespace realm;
36
using namespace realm::util;
37
using File = realm::util::File;
38
using MetadataMode = app::AppConfig::MetadataMode;
39

40
static const auto base_path =
41
    fs::path{util::make_temp_dir()}.make_preferred() / "realm_objectstore_sync_manager.test-dir";
42
static const std::string dummy_device_id = "123400000000000000000000";
43

44
TEST_CASE("App: path_for_realm API", "[sync][app][file]") {
26✔
45
    const std::string raw_url = "realms://realm.example.org/a/b/~/123456/xyz";
26✔
46

13✔
47
    SECTION("should work properly") {
26✔
48
        OfflineAppSession oas;
2✔
49
        auto user = oas.make_user();
2✔
50
        auto base_path =
2✔
51
            fs::path{oas.base_file_path()}.make_preferred() / "mongodb-realm" / "app_id" / user->user_id();
2✔
52
        const auto expected = base_path / "realms%3A%2F%2Frealm.example.org%2Fa%2Fb%2F%7E%2F123456%2Fxyz.realm";
2✔
53
        SyncConfig sync_config(user, bson::Bson{});
2✔
54
        REQUIRE(oas.app()->path_for_realm(sync_config, raw_url) == expected);
2!
55
        // This API should also generate the directory if it doesn't already exist.
1✔
56
        REQUIRE_DIR_PATH_EXISTS(base_path);
2!
57
    }
2✔
58

13✔
59
    SECTION("should produce the expected path for all partition key types") {
26✔
60
        OfflineAppSession oas;
24✔
61
        auto user = oas.make_user();
24✔
62
        auto base_path =
24✔
63
            fs::path{oas.base_file_path()}.make_preferred() / "mongodb-realm" / "app_id" / user->user_id();
24✔
64
        auto app = oas.app();
24✔
65
        // Directory should not be created until we get the path
12✔
66
        REQUIRE_DIR_PATH_DOES_NOT_EXIST(base_path);
24!
67

12✔
68
        SECTION("string") {
24✔
69
            const bson::Bson partition("string-partition-value&^#");
2✔
70
            SyncConfig config(user, partition);
2✔
71
            REQUIRE(app->path_for_realm(config) == base_path / "s_string-partition-value%26%5E%23.realm");
2!
72
        }
2✔
73

12✔
74
        SECTION("string which exceeds the file system path length limit") {
24✔
75
            const std::string name_too_long(500, 'b');
2✔
76
            REQUIRE(name_too_long.length() == 500);
2!
77
            const bson::Bson partition(name_too_long);
2✔
78
            SyncConfig config(user, partition);
2✔
79

1✔
80
            // Note: does not include `identity` as that's in the hashed part
1✔
81
            auto base_path = fs::path{oas.base_file_path()}.make_preferred() / "mongodb-realm" / "app_id";
2✔
82
            const std::string expected_suffix = ".realm";
2✔
83
            std::string actual = oas.app()->path_for_realm(config);
2✔
84
            size_t expected_length = base_path.string().length() + 1 + 64 + expected_suffix.length();
2✔
85
            REQUIRE(actual.length() == expected_length);
2!
86
            REQUIRE(StringData(actual).begins_with(base_path.string()));
2!
87
            REQUIRE(StringData(actual).ends_with(expected_suffix));
2!
88
        }
2✔
89

12✔
90
        SECTION("int32") {
24✔
91
            const bson::Bson partition(int32_t(-25));
2✔
92
            SyncConfig config(user, partition);
2✔
93
            REQUIRE(app->path_for_realm(config) == base_path / "i_-25.realm");
2!
94
        }
2✔
95

12✔
96
        SECTION("int64") {
24✔
97
            const bson::Bson partition(int64_t(1.15e18)); // > 32 bits
2✔
98
            SyncConfig config(user, partition);
2✔
99
            REQUIRE(app->path_for_realm(config) == base_path / "l_1150000000000000000.realm");
2!
100
        }
2✔
101

12✔
102
        SECTION("UUID") {
24✔
103
            const bson::Bson partition(UUID("3b241101-e2bb-4255-8caf-4136c566a961"));
2✔
104
            SyncConfig config(user, partition);
2✔
105
            REQUIRE(app->path_for_realm(config) == base_path / "u_3b241101-e2bb-4255-8caf-4136c566a961.realm");
2!
106
        }
2✔
107

12✔
108
        SECTION("ObjectId") {
24✔
109
            const bson::Bson partition(ObjectId("0123456789abcdefffffffff"));
2✔
110
            SyncConfig config(user, partition);
2✔
111
            REQUIRE(app->path_for_realm(config) == base_path / "o_0123456789abcdefffffffff.realm");
2!
112
        }
2✔
113

12✔
114
        SECTION("Null") {
24✔
115
            const bson::Bson partition;
2✔
116
            REQUIRE(partition.type() == bson::Bson::Type::Null);
2!
117
            SyncConfig config(user, partition);
2✔
118
            REQUIRE(app->path_for_realm(config) == base_path / "null.realm");
2!
119
        }
2✔
120

12✔
121
        SECTION("Flexible sync") {
24✔
122
            SyncConfig config(user, SyncConfig::FLXSyncEnabled{});
2✔
123
            REQUIRE(app->path_for_realm(config) == base_path / "flx_sync_default.realm");
2!
124
        }
2✔
125

12✔
126
        SECTION("Custom filename for Flexible Sync") {
24✔
127
            SyncConfig config(user, SyncConfig::FLXSyncEnabled{});
2✔
128
            REQUIRE(app->path_for_realm(config, util::make_optional<std::string>("custom")) ==
2!
129
                    base_path / "custom.realm");
2✔
130
        }
2✔
131

12✔
132
        SECTION("Custom filename with type will still append .realm") {
24✔
133
            SyncConfig config(user, SyncConfig::FLXSyncEnabled{});
2✔
134
            REQUIRE(app->path_for_realm(config, util::make_optional<std::string>("custom.foo")) ==
2!
135
                    base_path / "custom.foo.realm");
2✔
136
        }
2✔
137

12✔
138
        SECTION("Custom filename for Flexible Sync including .realm") {
24✔
139
            SyncConfig config(user, SyncConfig::FLXSyncEnabled{});
2✔
140
            REQUIRE(app->path_for_realm(config, util::make_optional<std::string>("custom.realm")) ==
2!
141
                    base_path / "custom.realm");
2✔
142
        }
2✔
143

12✔
144
        SECTION("Custom filename for Flexible Sync with an existing path") {
24✔
145
            SyncConfig config(user, SyncConfig::FLXSyncEnabled{});
2✔
146
            std::string path = app->path_for_realm(config, util::make_optional<std::string>("custom.realm"));
2✔
147
            realm::test_util::TestPathGuard guard(path);
2✔
148
            realm::util::File existing_realm_file(path, File::mode_Write);
2✔
149
            existing_realm_file.write(std::string("test"));
2✔
150
            existing_realm_file.sync();
2✔
151
            REQUIRE(app->path_for_realm(config, util::make_optional<std::string>("custom.realm")) ==
2!
152
                    base_path / "custom.realm");
2✔
153
        }
2✔
154

12✔
155
        // Should now exist after getting the path
12✔
156
        REQUIRE_DIR_PATH_EXISTS(base_path);
24!
157
    }
24✔
158
}
26✔
159

160
TEST_CASE("SyncManager: set_session_multiplexing", "[sync][sync manager]") {
4✔
161
    TestSyncManager::Config tsm_config;
4✔
162
    tsm_config.start_sync_client = false;
4✔
163
    TestSyncManager tsm(tsm_config);
4✔
164
    bool sync_multiplexing_allowed = GENERATE(true, false);
4✔
165
    auto sync_manager = tsm.sync_manager();
4✔
166
    sync_manager->set_session_multiplexing(sync_multiplexing_allowed);
4✔
167

2✔
168
    auto user_1 = tsm.fake_user("user-name-1");
4✔
169
    auto user_2 = tsm.fake_user("user-name-2");
4✔
170

2✔
171
    SyncTestFile file_1(user_1, "partition1", util::none);
4✔
172
    SyncTestFile file_2(user_1, "partition2", util::none);
4✔
173
    SyncTestFile file_3(user_2, "partition3", util::none);
4✔
174

2✔
175
    auto realm_1 = Realm::get_shared_realm(file_1);
4✔
176
    auto realm_2 = Realm::get_shared_realm(file_2);
4✔
177
    auto realm_3 = Realm::get_shared_realm(file_3);
4✔
178

2✔
179
    wait_for_download(*realm_1);
4✔
180
    wait_for_download(*realm_2);
4✔
181
    wait_for_download(*realm_3);
4✔
182

2✔
183
    if (sync_multiplexing_allowed) {
4✔
184
        REQUIRE(conn_id_for_realm(realm_1) == conn_id_for_realm(realm_2));
2!
185
        REQUIRE(conn_id_for_realm(realm_2) != conn_id_for_realm(realm_3));
2!
186
    }
2✔
187
    else {
2✔
188
        REQUIRE(conn_id_for_realm(realm_1) != conn_id_for_realm(realm_2));
2!
189
        REQUIRE(conn_id_for_realm(realm_2) != conn_id_for_realm(realm_3));
2!
190
        REQUIRE(conn_id_for_realm(realm_1) != conn_id_for_realm(realm_3));
2!
191
    }
2✔
192
}
4✔
193

194
TEST_CASE("SyncManager: has_existing_sessions", "[sync][sync manager][active sessions]") {
4✔
195
    TestSyncManager tsm({}, {false});
4✔
196
    auto sync_manager = tsm.sync_manager();
4✔
197

2✔
198
    SECTION("no active sessions") {
4✔
199
        REQUIRE(!sync_manager->has_existing_sessions());
2!
200
    }
2✔
201

2✔
202
    auto schema = Schema{
4✔
203
        {"object",
4✔
204
         {
4✔
205
             {"_id", PropertyType::Int, Property::IsPrimary{true}},
4✔
206
             {"value", PropertyType::Int},
4✔
207
         }},
4✔
208
    };
4✔
209

2✔
210
    std::atomic<bool> error_handler_invoked(false);
4✔
211
    Realm::Config config;
4✔
212
    auto user = tsm.fake_user("user-name");
4✔
213
    auto create_session = [&](SyncSessionStopPolicy stop_policy) {
3✔
214
        std::shared_ptr<SyncSession> session = sync_session(
2✔
215
            user, "/test-dying-state",
2✔
216
            [&](auto, auto) {
1✔
UNCOV
217
                error_handler_invoked = true;
×
UNCOV
218
            },
×
219
            stop_policy, nullptr, schema, &config);
2✔
220
        EventLoop::main().run_until([&] {
3✔
221
            return sessions_are_active(*session);
3✔
222
        });
3✔
223
        return session;
2✔
224
    };
2✔
225

2✔
226
    SECTION("active sessions") {
4✔
227
        {
2✔
228
            auto session = create_session(SyncSessionStopPolicy::Immediately);
2✔
229
            REQUIRE(sync_manager->has_existing_sessions());
2!
230
            session->close();
2✔
231
        }
2✔
232
        EventLoop::main().run_until([&] {
3✔
233
            return !sync_manager->has_existing_sessions();
3✔
234
        });
3✔
235
        REQUIRE(!sync_manager->has_existing_sessions());
2!
236
    }
2✔
237
}
4✔
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