Skip to content

Commit bd17af2

Browse files
author
Michael Wilkerson-Barker
authored
Replace TestAppSession close()/reopen() with scope based TestAppSession instance (#7672)
* Updated TestAppSession to remove close/reopen and take a config structure * Updated changelog and minor tweaks * AutoVerify email address matters... * Forgot to adjust format string * Updated REQUIRE's in TestAppSession to REALM_ASSERTs due to thread sanitizer
1 parent 58b0a87 commit bd17af2

File tree

7 files changed

+149
-103
lines changed

7 files changed

+149
-103
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
-----------
1818

1919
### Internals
20-
* None.
20+
* Update TestAppSession to allow scope-based usage for restarting the local app resources. ([PR #7672](https://github.com/realm/realm-core/pull/7672))
2121

2222
----------------------------------------------
2323

test/object-store/c_api/c_api.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6412,7 +6412,7 @@ TEST_CASE("C API app: link_user integration w/c_api transport", "[sync][app][c_a
64126412
auto user_data = new TestTransportUserData();
64136413
auto http_transport = realm_http_transport_new(send_request_to_server, user_data, user_data_free);
64146414
auto app_session = get_runtime_app_session();
6415-
TestAppSession session(app_session, *http_transport, DeleteApp{false});
6415+
TestAppSession session(app_session, {*http_transport}, DeleteApp{false});
64166416
realm_app app(session.app());
64176417

64186418
SECTION("remove_user integration") {

test/object-store/realm.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,16 +1464,22 @@ TEST_CASE("Synchronized realm: AutoOpen", "[sync][baas][pbs][async open]") {
14641464
std::mutex mutex;
14651465

14661466
// Create the app session and get the logged in user identity
1467-
auto server_app_config = minimal_app_config("autoopen-realm", schema);
1468-
TestAppSession session(create_app(server_app_config), transport, DeleteApp{true}, realm::ReconnectMode::normal,
1469-
socket_provider);
1470-
auto user = session.app()->current_user();
1471-
std::string identity = user->user_id();
1472-
REQUIRE(user->is_logged_in());
1473-
REQUIRE(!identity.empty());
1474-
// Reopen the App instance and retrieve the cached user
1475-
session.reopen(false);
1476-
user = session.app()->get_existing_logged_in_user(identity);
1467+
auto app_session = create_app(minimal_app_config("autoopen-realm", schema));
1468+
std::string identity;
1469+
TestAppSession::Config tas_config;
1470+
{
1471+
// Keep the app and realm storage
1472+
TestAppSession session(app_session, {transport, realm::ReconnectMode::normal, socket_provider},
1473+
DeleteApp{false}, false);
1474+
auto user = session.current_user();
1475+
REQUIRE(user);
1476+
REQUIRE(user->is_logged_in());
1477+
identity = user->user_id();
1478+
tas_config = session.config(); // get config with storage path and user creds populated
1479+
}
1480+
REQUIRE_FALSE(identity.empty());
1481+
TestAppSession session(app_session, tas_config);
1482+
auto user = session.app()->get_existing_logged_in_user(identity);
14771483

14781484
SyncTestFile config(user, partition, schema);
14791485
config.sync_config->cancel_waits_on_nonfatal_error = true;

test/object-store/sync/app.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,7 +2158,7 @@ TEST_CASE("app: mixed lists with object links", "[sync][pbs][app][links][baas]")
21582158
Mixed{target_id},
21592159
};
21602160
{
2161-
TestAppSession test_session(app_session, nullptr, DeleteApp{false});
2161+
TestAppSession test_session(app_session, {}, DeleteApp{false});
21622162
SyncTestFile config(test_session.app()->current_user(), partition, schema);
21632163
auto realm = Realm::get_shared_realm(config);
21642164

@@ -2222,7 +2222,7 @@ TEST_CASE("app: roundtrip values", "[sync][pbs][app][baas]") {
22222222
Decimal128 large_significand = Decimal128(70) / Decimal128(1.09);
22232223
auto obj_id = ObjectId::gen();
22242224
{
2225-
TestAppSession test_session(app_session, nullptr, DeleteApp{false});
2225+
TestAppSession test_session(app_session, {}, DeleteApp{false});
22262226
SyncTestFile config(test_session.app()->current_user(), partition, schema);
22272227
auto realm = Realm::get_shared_realm(config);
22282228

@@ -2646,7 +2646,7 @@ TEST_CASE("app: sync integration", "[sync][pbs][app][baas]") {
26462646
}
26472647

26482648
auto transport = std::make_shared<HookedTransport<>>();
2649-
TestAppSession hooked_session(session.app_session(), transport, DeleteApp{false});
2649+
TestAppSession hooked_session(session.app_session(), {transport}, DeleteApp{false});
26502650
auto app = hooked_session.app();
26512651
std::shared_ptr<User> user = app->current_user();
26522652
REQUIRE(user);
@@ -2704,7 +2704,7 @@ TEST_CASE("app: sync integration", "[sync][pbs][app][baas]") {
27042704
}
27052705

27062706
auto transport = std::make_shared<HookedTransport<>>();
2707-
TestAppSession hooked_session(session.app_session(), transport, DeleteApp{false});
2707+
TestAppSession hooked_session(session.app_session(), {transport}, DeleteApp{false});
27082708
auto app = hooked_session.app();
27092709
std::shared_ptr<User> user = app->current_user();
27102710
REQUIRE(user);
@@ -3306,8 +3306,9 @@ TEST_CASE("app: sync logs contain baas coid", "[sync][app][baas]") {
33063306

33073307
auto in_mem_logger = std::make_shared<InMemoryLogger>();
33083308
in_mem_logger->set_level_threshold(InMemoryLogger::Level::all);
3309-
TestAppSession app_session(get_runtime_app_session(), nullptr, DeleteApp{false}, ReconnectMode::normal, nullptr,
3310-
in_mem_logger);
3309+
TestAppSession::Config session_config;
3310+
session_config.logger = in_mem_logger;
3311+
TestAppSession app_session(get_runtime_app_session(), session_config, DeleteApp{false});
33113312

33123313
const auto partition = random_string(100);
33133314
SyncTestFile config(app_session.app()->current_user(), partition, util::none);
@@ -4521,7 +4522,7 @@ TEST_CASE("app: full-text compatible with sync", "[sync][app][baas]") {
45214522
auto server_app_config = minimal_app_config("full_text", schema);
45224523
auto app_session = create_app(server_app_config);
45234524
const auto partition = random_string(100);
4524-
TestAppSession test_session(app_session, nullptr);
4525+
TestAppSession test_session(app_session);
45254526
SyncTestFile config(test_session.app()->current_user(), partition, schema);
45264527
SharedRealm realm;
45274528
SECTION("sync open") {

test/object-store/util/sync/flx_sync_harness.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,17 @@ class FLXSyncTestHarness {
8484
};
8585

8686
explicit FLXSyncTestHarness(Config&& config)
87-
: m_test_session(make_app_from_server_schema(config.test_name, config.server_schema), config.transport, true,
88-
config.reconnect_mode, config.custom_socket_provider)
87+
: m_test_session(make_app_from_server_schema(config.test_name, config.server_schema),
88+
{config.transport, config.reconnect_mode, config.custom_socket_provider}, DeleteApp{true})
8989
, m_schema(std::move(config.server_schema.schema))
9090
{
9191
}
9292
FLXSyncTestHarness(const std::string& test_name, ServerSchema server_schema = default_server_schema(),
9393
std::shared_ptr<GenericNetworkTransport> transport = instance_of<SynchronousTestTransport>,
9494
std::shared_ptr<realm::sync::SyncSocketProvider> custom_socket_provider = nullptr)
95-
: m_test_session(make_app_from_server_schema(test_name, server_schema), std::move(transport), true,
96-
realm::ReconnectMode::normal, custom_socket_provider)
95+
: m_test_session(make_app_from_server_schema(test_name, server_schema),
96+
{std::move(transport), realm::ReconnectMode::normal, custom_socket_provider},
97+
DeleteApp{true})
9798
, m_schema(std::move(server_schema.schema))
9899
{
99100
}

test/object-store/util/test_file.cpp

Lines changed: 85 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -329,36 +329,47 @@ void set_app_config_defaults(app::AppConfig& app_config,
329329
#if REALM_ENABLE_AUTH_TESTS
330330

331331
TestAppSession::TestAppSession()
332-
: TestAppSession(get_runtime_app_session(), nullptr, DeleteApp{false})
332+
// Don't delete the global runtime app session
333+
: TestAppSession(get_runtime_app_session(), {}, DeleteApp{false})
333334
{
334335
}
335336

336-
TestAppSession::TestAppSession(AppSession session,
337-
std::shared_ptr<realm::app::GenericNetworkTransport> custom_transport,
338-
DeleteApp delete_app, ReconnectMode reconnect_mode,
339-
std::shared_ptr<realm::sync::SyncSocketProvider> custom_socket_provider,
340-
std::shared_ptr<realm::util::Logger> logger)
337+
TestAppSession::TestAppSession(AppSession session)
338+
: TestAppSession(session, {}, DeleteApp{true})
339+
{
340+
}
341+
342+
TestAppSession::TestAppSession(AppSession session, Config config, DeleteApp delete_app, bool delete_storage)
341343
: m_app_session(std::make_unique<AppSession>(session))
342-
, m_base_file_path(util::make_temp_dir() + random_string(10))
344+
, m_config(config)
343345
, m_delete_app(delete_app)
344-
, m_transport(custom_transport)
346+
, m_delete_storage(delete_storage)
345347
{
346-
if (!m_transport)
347-
m_transport = instance_of<SynchronousTestTransport>;
348-
app_config = get_config(m_transport, *m_app_session);
349-
set_app_config_defaults(app_config, m_transport);
350-
app_config.base_file_path = m_base_file_path;
351-
app_config.metadata_mode = realm::app::AppConfig::MetadataMode::NoEncryption;
348+
if (!m_config.storage_path || m_config.storage_path->empty()) {
349+
m_config.storage_path.emplace(util::make_temp_dir() + random_string(10));
350+
}
351+
REALM_ASSERT(m_config.storage_path);
352+
util::try_make_dir(*m_config.storage_path);
352353

353-
util::try_make_dir(m_base_file_path);
354-
app_config.sync_client_config.reconnect_mode = reconnect_mode;
355-
app_config.sync_client_config.socket_provider = custom_socket_provider;
354+
if (!m_config.transport) {
355+
m_config.transport = instance_of<SynchronousTestTransport>;
356+
}
357+
realm::app::AppConfig app_config = get_config(m_config.transport, *m_app_session);
358+
set_app_config_defaults(app_config, m_config.transport);
359+
// If a base URL was provided, set it in the app config
360+
if (m_config.base_url) {
361+
app_config.base_url = *m_config.base_url;
362+
}
363+
app_config.base_file_path = *m_config.storage_path;
364+
app_config.metadata_mode = m_config.metadata_mode;
365+
app_config.sync_client_config.reconnect_mode = m_config.reconnect_mode;
356366
// With multiplexing enabled, the linger time controls how long a
357367
// connection is kept open for reuse. In tests, we want to shut
358368
// down sync clients immediately.
359369
app_config.sync_client_config.timeouts.connection_linger_time = 0;
360-
if (logger) {
361-
app_config.sync_client_config.logger_factory = [logger](util::Logger::Level) {
370+
app_config.sync_client_config.socket_provider = m_config.socket_provider;
371+
if (m_config.logger) {
372+
app_config.sync_client_config.logger_factory = [logger = m_config.logger](util::Logger::Level) {
362373
return logger;
363374
};
364375
}
@@ -367,70 +378,80 @@ TestAppSession::TestAppSession(AppSession session,
367378

368379
// initialize sync client
369380
m_app->sync_manager()->get_sync_client();
370-
user_creds = create_user_and_log_in(m_app);
381+
// If no user creds are supplied, then create the user and log in
382+
if (!m_config.user_creds) {
383+
auto result = create_user_and_log_in();
384+
REALM_ASSERT(result.is_ok());
385+
m_config.user_creds = result.get_value();
386+
}
387+
// If creds are supplied, it is up to the caller to log in separately
371388
}
372389

373390
TestAppSession::~TestAppSession()
374391
{
375-
if (util::File::exists(m_base_file_path)) {
392+
if (m_app) {
393+
m_app->sync_manager()->tear_down_for_testing();
394+
m_app.reset();
395+
}
396+
app::App::clear_cached_apps();
397+
// If the app session is being deleted or the config tells us to, delete the storage path
398+
if ((m_delete_app || m_delete_storage) && util::File::exists(*m_config.storage_path)) {
376399
try {
377-
m_app->sync_manager()->tear_down_for_testing();
378-
util::try_remove_dir_recursive(m_base_file_path);
400+
util::try_remove_dir_recursive(*m_config.storage_path);
379401
}
380402
catch (const std::exception& ex) {
381-
std::cerr << ex.what() << "\n";
403+
std::cerr << "Error tearing down TestAppSession(" << m_app_session->config.app_name << "): " << ex.what()
404+
<< "\n";
382405
}
383-
app::App::clear_cached_apps();
384406
}
385-
if (m_delete_app) {
407+
if (m_delete_app && m_app_session) {
386408
m_app_session->admin_api.delete_app(m_app_session->server_app_id);
387409
}
388410
}
389411

390-
void TestAppSession::close(bool tear_down)
412+
StatusWith<realm::app::AppCredentials> TestAppSession::create_user_and_log_in()
391413
{
392-
try {
393-
if (tear_down) {
394-
// If tearing down, make sure there's an app to work with
395-
if (!m_app) {
396-
reopen(false);
414+
REALM_ASSERT(m_app);
415+
AutoVerifiedEmailCredentials creds;
416+
auto pf = util::make_promise_future<void>();
417+
m_app->provider_client<app::App::UsernamePasswordProviderClient>().register_email(
418+
creds.email, creds.password,
419+
[this, &creds, promise = util::CopyablePromiseHolder<void>(std::move(pf.promise))](
420+
util::Optional<app::AppError> error) mutable {
421+
if (error) {
422+
promise.get_promise().set_error(error->to_status());
423+
return;
397424
}
398-
REALM_ASSERT(m_app);
399-
// Clean up the app data
400-
m_app->sync_manager()->tear_down_for_testing();
401-
}
402-
else if (m_app) {
403-
// Otherwise, make sure all the session are closed
404-
m_app->sync_manager()->close_all_sessions();
405-
}
406-
m_app.reset();
407-
408-
// If tearing down, clean up the test file directory
409-
if (tear_down && !m_base_file_path.empty() && util::File::exists(m_base_file_path)) {
410-
util::try_remove_dir_recursive(m_base_file_path);
411-
m_base_file_path.clear();
412-
}
413-
}
414-
catch (const std::exception& ex) {
415-
std::cerr << "Error tearing down TestAppSession: " << ex.what() << "\n";
425+
auto result = log_in_user(creds);
426+
if (!result.is_ok()) {
427+
promise.get_promise().set_error(result.get_status());
428+
return;
429+
}
430+
promise.get_promise().emplace_value();
431+
});
432+
auto result = pf.future.get_no_throw();
433+
if (!result.is_ok()) {
434+
return result;
416435
}
417-
// Ensure all cached apps are cleared
418-
app::App::clear_cached_apps();
436+
return creds;
419437
}
420438

421-
void TestAppSession::reopen(bool log_in)
439+
StatusWith<std::shared_ptr<realm::SyncUser>>
440+
TestAppSession::log_in_user(std::optional<realm::app::AppCredentials> user_creds)
422441
{
423-
REALM_ASSERT(!m_base_file_path.empty());
424-
if (m_app) {
425-
close(false);
426-
}
427-
m_app = app::App::get_app(app::App::CacheMode::Disabled, app_config);
428-
429-
// initialize sync client
430-
m_app->sync_manager()->get_sync_client();
431-
if (log_in) {
432-
log_in_user(m_app, user_creds);
433-
}
442+
REALM_ASSERT(m_app);
443+
REALM_ASSERT((user_creds || m_config.user_creds));
444+
auto pf = util::make_promise_future<std::shared_ptr<realm::SyncUser>>();
445+
m_app->log_in_with_credentials(
446+
*user_creds, [promise = util::CopyablePromiseHolder<std::shared_ptr<realm::SyncUser>>(std::move(pf.promise))](
447+
std::shared_ptr<realm::SyncUser> user, util::Optional<app::AppError> error) mutable {
448+
if (error) {
449+
promise.get_promise().set_error(error->to_status());
450+
return;
451+
}
452+
promise.get_promise().emplace_value(user);
453+
});
454+
return pf.future.get_no_throw();
434455
}
435456

436457
std::vector<bson::BsonDocument> TestAppSession::get_documents(app::User& user, const std::string& object_type,

0 commit comments

Comments
 (0)