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

realm / realm-core / daniel.tabacaru_887

07 Aug 2024 08:36PM UTC coverage: 91.108% (+0.02%) from 91.087%
daniel.tabacaru_887

Pull #7963

Evergreen

danieltabacaru
Unregister SyncSession callbacks when SyncManager is destroyed
Pull Request #7963: RJS-2784 Fix callback crashes when reloading with React Native

102796 of 181584 branches covered (56.61%)

35 of 37 new or added lines in 2 files covered. (94.59%)

294 existing lines in 9 files now uncovered.

217072 of 238259 relevant lines covered (91.11%)

5903576.39 hits per line

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

94.74
/test/object-store/sync/session/connection_change_notifications.cpp
1
////////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright 2018 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_utils.hpp>
21
#include <util/sync/session_util.hpp>
22

23
using namespace realm;
24
using namespace realm::util;
25

26
TEST_CASE("sync: Connection state changes", "[sync][session][connection change]") {
8✔
27
    if (!EventLoop::has_implementation())
8✔
28
        return;
×
29

30
    TestSyncManager tsm;
8✔
31
    auto user = tsm.fake_user();
8✔
32

33
    SECTION("register connection change listener") {
8✔
34
        auto session = sync_session(
2✔
35
            user, "/connection-state-changes-1", [](auto, auto) {}, SyncSessionStopPolicy::AfterChangesUploaded);
2✔
36

37
        EventLoop::main().run_until([&] {
3✔
38
            return sessions_are_active(*session);
3✔
39
        });
3✔
40
        EventLoop::main().run_until([&] {
2,220✔
41
            return sessions_are_connected(*session);
2,220✔
42
        });
2,220✔
43

44
        std::atomic<bool> listener_called(false);
2✔
45
        session->register_connection_change_callback([&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
46
            listener_called = true;
2✔
47
        });
2✔
48

49
        user->log_out();
2✔
50
        EventLoop::main().run_until([&] {
3✔
51
            return sessions_are_disconnected(*session);
3✔
52
        });
3✔
53
        REQUIRE(listener_called == true);
2!
54
    }
2✔
55

56
    SECTION("unregister connection change listener") {
8✔
57
        auto session = sync_session(
2✔
58
            user, "/connection-state-changes-2", [](auto, auto) {}, SyncSessionStopPolicy::AfterChangesUploaded);
2✔
59

60
        EventLoop::main().run_until([&] {
3✔
61
            return sessions_are_active(*session);
3✔
62
        });
3✔
63
        EventLoop::main().run_until([&] {
2,063✔
64
            return sessions_are_connected(*session);
2,063✔
65
        });
2,063✔
66

67
        std::atomic<size_t> listener1_call_cnt(0);
2✔
68
        std::atomic<bool> listener2_called(false);
2✔
69

70
        auto token1 = session->register_connection_change_callback(
2✔
71
            [&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
72
                ++listener1_call_cnt;
×
73
            });
×
74
        session->unregister_connection_change_callback(token1);
2✔
75
        // One call may have been in progress when unregistered
76
        REQUIRE(listener1_call_cnt <= 1);
2!
77
        size_t listener1_called = listener1_call_cnt;
2✔
78

79
        session->register_connection_change_callback([&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
80
            listener2_called = true;
2✔
81
        });
2✔
82
        user->log_out();
2✔
83
        REQUIRE(sessions_are_disconnected(*session));
2!
84
        // ensure callback 1 was not called anymore
85
        REQUIRE(listener1_call_cnt == listener1_called);
2!
86
        REQUIRE(listener2_called);
2!
87
    }
2✔
88

89
    SECTION("unregister connection change listener during callback") {
8✔
90
        int listener1_call_cnt = 0;
2✔
91
        auto session = sync_session(
2✔
92
            user, "/connection-state-changes-3", [](auto, auto) {}, SyncSessionStopPolicy::AfterChangesUploaded);
2✔
93
        std::mutex mutex;
2✔
94
        std::unique_lock lock(mutex);
2✔
95
        uint64_t token1 = session->register_connection_change_callback(
2✔
96
            [&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
97
                std::lock_guard lock(mutex);
2✔
98
                ++listener1_call_cnt;
2✔
99
                session->unregister_connection_change_callback(token1);
2✔
100
            });
2✔
101
        lock.unlock();
2✔
102

103
        EventLoop::main().run_until([&] {
3✔
104
            return sessions_are_active(*session);
3✔
105
        });
3✔
106
        EventLoop::main().run_until([&] {
1,795✔
107
            return sessions_are_connected(*session);
1,795✔
108
        });
1,795✔
109

110
        bool listener2_called = false;
2✔
111
        session->register_connection_change_callback([&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
112
            listener2_called = true;
2✔
113
        });
2✔
114

115
        user->log_out();
2✔
116
        REQUIRE(sessions_are_disconnected(*session));
2!
117
        REQUIRE(listener1_call_cnt == 1); // Only called once before unregister
2!
118
        REQUIRE(listener2_called);
2!
119
    }
2✔
120

121
    SECTION("Callback not invoked when SyncSession is detached from SyncManager") {
8✔
122
        auto session = sync_session(
2✔
123
            user, "/connection-state-changes-1", [](auto, auto) {}, SyncSessionStopPolicy::AfterChangesUploaded);
2✔
124

125
        EventLoop::main().run_until([&] {
3✔
126
            return sessions_are_active(*session);
3✔
127
        });
3✔
128
        EventLoop::main().run_until([&] {
1,923✔
129
            return sessions_are_connected(*session);
1,923✔
130
        });
1,923✔
131

132
        bool listener_called = false;
2✔
133
        session->register_connection_change_callback([&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
NEW
134
            listener_called = true;
×
NEW
135
        });
×
136

137
        session->detach_from_sync_manager();
2✔
138
        REQUIRE_FALSE(listener_called);
2!
139
    }
2✔
140
}
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