@@ -329,36 +329,47 @@ void set_app_config_defaults(app::AppConfig& app_config,
329
329
#if REALM_ENABLE_AUTH_TESTS
330
330
331
331
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 })
333
334
{
334
335
}
335
336
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)
341
343
: m_app_session(std::make_unique<AppSession>(session))
342
- , m_base_file_path(util::make_temp_dir() + random_string( 10 ) )
344
+ , m_config(config )
343
345
, m_delete_app(delete_app)
344
- , m_transport(custom_transport )
346
+ , m_delete_storage(delete_storage )
345
347
{
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 );
352
353
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 ;
356
366
// With multiplexing enabled, the linger time controls how long a
357
367
// connection is kept open for reuse. In tests, we want to shut
358
368
// down sync clients immediately.
359
369
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) {
362
373
return logger;
363
374
};
364
375
}
@@ -367,70 +378,80 @@ TestAppSession::TestAppSession(AppSession session,
367
378
368
379
// initialize sync client
369
380
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
371
388
}
372
389
373
390
TestAppSession::~TestAppSession ()
374
391
{
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 )) {
376
399
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 );
379
401
}
380
402
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 " ;
382
405
}
383
- app::App::clear_cached_apps ();
384
406
}
385
- if (m_delete_app) {
407
+ if (m_delete_app && m_app_session ) {
386
408
m_app_session->admin_api .delete_app (m_app_session->server_app_id );
387
409
}
388
410
}
389
411
390
- void TestAppSession::close ( bool tear_down )
412
+ StatusWith<realm::app::AppCredentials> TestAppSession::create_user_and_log_in ( )
391
413
{
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 ;
397
424
}
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;
416
435
}
417
- // Ensure all cached apps are cleared
418
- app::App::clear_cached_apps ();
436
+ return creds;
419
437
}
420
438
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)
422
441
{
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 ();
434
455
}
435
456
436
457
std::vector<bson::BsonDocument> TestAppSession::get_documents (app::User& user, const std::string& object_type,
0 commit comments