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

realm / realm-core / 2439

20 Jun 2024 08:47PM UTC coverage: 90.962% (+0.006%) from 90.956%
2439

push

Evergreen

web-flow
RCORE-2172 Fix race condition in "unregister connection change listener" test while listener is being unregistered (#7824)

* Fixed race in 'unregister connection change listener' test

* Updated test per review

* Updates from review

102170 of 180382 branches covered (56.64%)

30 of 31 new or added lines in 1 file covered. (96.77%)

60 existing lines in 10 files now uncovered.

214712 of 236047 relevant lines covered (90.96%)

5336875.2 hits per line

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

96.05
/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]") {
6✔
27
    if (!EventLoop::has_implementation())
6✔
28
        return;
×
29

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

33
    SECTION("register connection change listener") {
6✔
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([&] {
1,827✔
41
            return sessions_are_connected(*session);
1,827✔
42
        });
1,827✔
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") {
6✔
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([&] {
1,814✔
64
            return sessions_are_connected(*session);
1,814✔
65
        });
1,814✔
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✔
NEW
72
                listener1_call_cnt = listener1_call_cnt + 1;
×
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") {
6✔
90
        uint64_t token1;
2✔
91
        std::atomic<int> listener1_call_cnt(0);
2✔
92
        std::atomic<bool> listener2_called(false);
2✔
93
        auto session = sync_session(
2✔
94
            user, "/connection-state-changes-3", [](auto, auto) {}, SyncSessionStopPolicy::AfterChangesUploaded);
2✔
95
        token1 = session->register_connection_change_callback(
2✔
96
            [&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
97
                listener1_call_cnt = listener1_call_cnt + 1;
2✔
98
                session->unregister_connection_change_callback(token1);
2✔
99
            });
2✔
100

101
        EventLoop::main().run_until([&] {
3✔
102
            return sessions_are_active(*session);
3✔
103
        });
3✔
104
        EventLoop::main().run_until([&] {
2,239✔
105
            return sessions_are_connected(*session);
2,239✔
106
        });
2,239✔
107

108
        session->register_connection_change_callback([&](SyncSession::ConnectionState, SyncSession::ConnectionState) {
2✔
109
            listener2_called = true;
2✔
110
        });
2✔
111

112
        user->log_out();
2✔
113
        REQUIRE(sessions_are_disconnected(*session));
2!
114
        REQUIRE(listener1_call_cnt == 1); // Only called once before unregister
2!
115
        REQUIRE(listener2_called);
2!
116
    }
2✔
117
}
6✔
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