Skip to content

Commit

Permalink
Update for the app services split branch
Browse files Browse the repository at this point in the history
  • Loading branch information
tgoyne committed Apr 27, 2024
1 parent 3a9586b commit 2ea8d98
Show file tree
Hide file tree
Showing 41 changed files with 350 additions and 300 deletions.
45 changes: 38 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
x.y.z Release notes (yyyy-MM-dd)
=============================================================
### Enhancements
* Added `SyncConfiguration.initialSubscriptions` which describes the initial subscription configuration that was passed when constructing the `SyncConfiguration`. ([#8548](https://github.com/realm/realm-swift/issues/8548))

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-swift/issues/????), since v?.?.?)
* None.
* Added `SyncConfiguration.initialSubscriptions` which describes the initial
subscription configuration that was passed when constructing the
`SyncConfiguration`. ([#8548](https://github.com/realm/realm-swift/issues/8548))
* When connecting to multiple server apps, a unique encryption key is used for
each of the metadata Realms rather than sharing one between them
([Core #7552](https://github.com/realm/realm-core/pull/7552)).
* Improve perfomance of IN queries and chained OR equality queries for
UUID/ObjectId types. ([.Net * #3566](https://github.com/realm/realm-dotnet/issues/3566))

### Fixed
* `-[RLMUser allSessions]` did not include sessions which were currently
waiting for an access token despite including sessions in other non-active
states. ([Core #7300](https://github.com/realm/realm-core/pull/7300), since v10.0.0).
* `[RLMApp allUsers]` included users which were logged out during the current
run of the app, but not users which had previously been logged out. It now
always includes all logged out users. ([Core #7300](https://github.com/realm/realm-core/pull/7300), since v10.0.0).
* Deleting the active user (via `User.delete()`) left the active user
unset rather than selecting another logged-in user as the active user like
logging out and removing users does. ([Core #7300](https://github.com/realm/realm-core/pull/7300), since v10.23.0).
* Fixed several issues around copying an encrypted Realm between platforms with
different page sizes (such as between x86_64 and arm64 Apple platforms):
- Fixed `Assertion failed: new_size % (1ULL << m_page_shift) == 0` when
opening an encrypted Realm less than 64Mb that was generated on a platform
with a different page size than the current platform.
([Core #7322](https://github.com/realm/realm-core/issues/7322), since v10.42.0)
- Fixed a `DecryptionFailed` exception thrown when opening a small (<4k of
data) Realm generated on a device with a page size of 4k if it was bundled
and opened on a device with a larger page size (since the beginning).
- Fixed an issue during a subsequent open of an encrypted Realm for some rare
allocation patterns when the top ref was within ~50 bytes of the end of a
page. This could manifest as a DecryptionFailed exception or as an
assertion: `encrypted_file_mapping.hpp:183: Assertion failed: local_ndx <
m_page_state.size()`. ([Core #7319](https://github.com/realm/realm-core/issues/7319))
* Schema initialization could hit an assertion failure if the sync client
applied a downloaded changeset while the Realm file was in the process of
being opened ([#7041](https://github.com/realm/realm-core/issues/7041), since v10.15.0).

<!-- ### Breaking Changes - ONLY INCLUDE FOR NEW MAJOR version -->

Expand All @@ -14,10 +45,10 @@ x.y.z Release notes (yyyy-MM-dd)
* APIs are backwards compatible with all previous releases in the 10.x.y series.
* Carthage release for Swift is built with Xcode 15.3.0.
* CocoaPods: 1.10 or later.
* Xcode: 14.2-15.3.0.
* Xcode: 14.2-15.3.0. Note that this will be the final release to support Xcode 14.

### Internal
* Upgraded realm-core from ? to ?
* Upgraded realm-core from v14.5.2 to 14.6.0

10.49.2 Release notes (2024-04-17)
=============================================================
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import PackageDescription
import Foundation

let coreVersion = Version("14.5.2")
let coreVersion = Version("14.6.0")
let cocoaVersion = Version("10.49.2")

let cxxSettings: [CXXSetting] = [
Expand Down
2 changes: 1 addition & 1 deletion Realm/ObjectServerTests/ClientResetTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class ClientResetTests: SwiftSyncTestCase {
}
XCTAssertTrue(path.contains("mongodb-realm/\(app.appId)/recovered-realms/recovered_realm"))
XCTAssertFalse(FileManager.default.fileExists(atPath: path))
SyncSession.immediatelyHandleError(token, syncManager: app.syncManager)
SyncSession.immediatelyHandleError(token)
XCTAssertTrue(FileManager.default.fileExists(atPath: path))
ex.fulfill()
}
Expand Down
11 changes: 6 additions & 5 deletions Realm/ObjectServerTests/RLMMongoClientTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#import "RLMBSON_Private.hpp"
#import "RLMUser_Private.hpp"

#import <realm/object-store/sync/app_user.hpp>
#import <realm/object-store/sync/sync_manager.hpp>
#import <realm/util/bson/bson.hpp>

Expand Down Expand Up @@ -735,8 +736,8 @@ - (void)performMultipleWatchStreamsTest:(nullable dispatch_queue_t)delegateQueue
s << RLMConvertRLMBSONToBson(partitionValue);
// Intentionally not passing the correct partition value here as we (accidentally?)
// don't use the filename generated from the partition value
realm::SyncConfig config(user._syncUser, "null");
return @(user._syncUser->sync_manager()->path_for_realm(config, s.str()).c_str());
realm::SyncConfig config(user.user, "null");
return @(user.user->path_for_realm(config, s.str()).c_str());
}

- (void)testSyncFilePaths {
Expand All @@ -763,10 +764,10 @@ - (void)testSyncFilePaths {
}

static NSString *oldPathForPartitionValue(RLMUser *user, NSString *oldName) {
realm::SyncConfig config(user._syncUser, "null");
realm::SyncConfig config(user.user, "null");
return [NSString stringWithFormat:@"%@/%s%@.realm",
[@(user._syncUser->sync_manager()->path_for_realm(config).c_str()) stringByDeletingLastPathComponent],
user._syncUser->identity().c_str(), oldName];
[@(user.user->path_for_realm(config).c_str()) stringByDeletingLastPathComponent],
user.user->user_id().c_str(), oldName];
}

- (void)testLegacyFilePathsAreUsedIfFilesArePresent {
Expand Down
29 changes: 16 additions & 13 deletions Realm/ObjectServerTests/RLMObjectServerTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#import "RLMWatchTestUtility.h"

#import <realm/object-store/shared_realm.hpp>
#import <realm/object-store/sync/app_user.hpp>
#import <realm/object-store/sync/sync_manager.hpp>
#import <realm/object-store/thread_safe_reference.hpp>
#import <realm/util/file.hpp>
Expand Down Expand Up @@ -166,7 +167,7 @@ - (void)testRemoveUser {
}

- (void)testDeleteUser {
[self createUser];
RLMUser *firstUser = [self createUser];
RLMUser *secondUser = [self createUser];

XCTAssert([self.app.currentUser.identifier isEqualToString:secondUser.identifier]);
Expand All @@ -176,7 +177,7 @@ - (void)testDeleteUser {
[secondUser deleteWithCompletion:^(NSError *error) {
XCTAssert(!error);
XCTAssert(self.app.allUsers.count == 1);
XCTAssertNil(self.app.currentUser);
XCTAssertEqualObjects(self.app.currentUser, firstUser);
XCTAssertEqual(secondUser.state, RLMUserStateRemoved);
[deleteUserExpectation fulfill];
}];
Expand Down Expand Up @@ -560,7 +561,7 @@ - (void)testSyncErrorHandlerErrorDomain {
#pragma mark - User Profile

- (void)testUserProfileInitialization {
RLMUserProfile *profile = [[RLMUserProfile alloc] initWithUserProfile:realm::SyncUserProfile()];
RLMUserProfile *profile = [[RLMUserProfile alloc] initWithUserProfile:realm::app::UserProfile()];
XCTAssertNil(profile.name);
XCTAssertNil(profile.maxAge);
XCTAssertNil(profile.minAge);
Expand All @@ -572,7 +573,7 @@ - (void)testUserProfileInitialization {

auto metadata = realm::bson::BsonDocument({{"some_key", "some_value"}});

profile = [[RLMUserProfile alloc] initWithUserProfile:realm::SyncUserProfile(realm::bson::BsonDocument({
profile = [[RLMUserProfile alloc] initWithUserProfile:realm::app::UserProfile(realm::bson::BsonDocument({
{"name", "Jane"},
{"max_age", "40"},
{"min_age", "30"},
Expand Down Expand Up @@ -758,7 +759,10 @@ - (void)testSessionRefresh {

// Should result in an access token error followed by a refresh when we
// open the Realm which is entirely transparent to the user
user._syncUser->update_access_token(self.badAccessToken.UTF8String);
realm::RealmJWT token(std::string_view(self.badAccessToken));
user.user->update_data_for_testing([&](auto& data) {
data.access_token = token;
});
RLMRealm *realm = [self openRealmForPartitionValue:self.name user:user];

RLMRealm *realm2 = [self openRealm];
Expand Down Expand Up @@ -895,7 +899,7 @@ - (void)testEncryptedSyncedRealmWrongKey {
c.encryptionKey = RLMGenerateKey();
RLMAssertRealmExceptionContains([RLMRealm realmWithConfiguration:c error:nil],
RLMErrorInvalidDatabase,
@"Failed to open Realm file at path '%@': Realm file decryption failed (Decryption failed: 'unable to decrypt after 0 seconds",
@"Failed to open Realm file at path '%@': Realm file decryption failed (Decryption failed: unable to decrypt after 0 seconds",
c.fileURL.path);
}

Expand Down Expand Up @@ -1367,8 +1371,7 @@ - (void)testClientResetManualInitiation {
// At this point the Realm should be invalidated and client reset should be possible.
NSString *pathValue = [theError rlmSync_clientResetBackedUpRealmPath];
XCTAssertFalse([NSFileManager.defaultManager fileExistsAtPath:pathValue]);
[RLMSyncSession immediatelyHandleError:theError.rlmSync_errorActionToken
syncManager:self.app.syncManager];
[RLMSyncSession immediatelyHandleError:theError.rlmSync_errorActionToken];
XCTAssertTrue([NSFileManager.defaultManager fileExistsAtPath:pathValue]);
}

Expand Down Expand Up @@ -2016,8 +2019,8 @@ - (void)testWriteCopyForConfigurationLocalRealmForSyncWithExistingData {
s << RLMConvertRLMBSONToBson(partitionValue);
// Intentionally not passing the correct partition value here as we (accidentally?)
// don't use the filename generated from the partition value
realm::SyncConfig config(user._syncUser, "null");
return @(user._syncUser->sync_manager()->path_for_realm(config, s.str()).c_str());
realm::SyncConfig config(user.user, "null");
return @(user.user->path_for_realm(config, s.str()).c_str());
}

- (void)testSyncFilePaths {
Expand All @@ -2044,10 +2047,10 @@ - (void)testSyncFilePaths {
}

static NSString *oldPathForPartitionValue(RLMUser *user, NSString *oldName) {
realm::SyncConfig config(user._syncUser, "null");
realm::SyncConfig config(user.user, "null");
return [NSString stringWithFormat:@"%@/%s%@.realm",
[@(user._syncUser->sync_manager()->path_for_realm(config).c_str()) stringByDeletingLastPathComponent],
user._syncUser->identity().c_str(), oldName];
[@(user.user->path_for_realm(config).c_str()) stringByDeletingLastPathComponent],
user.user->user_id().c_str(), oldName];
}

- (void)testLegacyFilePathsAreUsedIfFilesArePresent {
Expand Down
2 changes: 1 addition & 1 deletion Realm/ObjectServerTests/RLMSyncTestCase.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ RLM_HEADER_AUDIT_BEGIN(nullability, sendability)

- (void)resetSyncManager;

- (NSString *)badAccessToken;
- (const char *)badAccessToken;

- (void)cleanupRemoteDocuments:(RLMMongoCollection *)collection;

Expand Down
43 changes: 20 additions & 23 deletions Realm/ObjectServerTests/RLMSyncTestCase.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@
#import <XCTest/XCTest.h>
#import <Realm/Realm.h>

#import "RLMApp_Private.hpp"
#import "RLMChildProcessEnvironment.h"
#import "RLMRealmConfiguration_Private.h"
#import "RLMRealmUtil.hpp"
#import "RLMRealm_Dynamic.h"
#import "RLMRealm_Private.hpp"
#import "RLMRealmConfiguration_Private.h"
#import "RLMSyncManager_Private.hpp"
#import "RLMSyncConfiguration_Private.h"
#import "RLMSyncManager_Private.hpp"
#import "RLMUser_Private.hpp"
#import "RLMUtil.hpp"
#import "RLMApp_Private.hpp"
#import "RLMChildProcessEnvironment.h"
#import "RLMRealmUtil.hpp"

#import <realm/object-store/sync/app_user.hpp>
#import <realm/object-store/sync/sync_manager.hpp>
#import <realm/object-store/sync/sync_session.hpp>
#import <realm/object-store/sync/sync_user.hpp>

#if TARGET_OS_OSX

Expand All @@ -55,10 +56,6 @@ - (BOOL)waitForUploadCompletionOnQueue:(dispatch_queue_t)queue callback:(void(^)
- (BOOL)waitForDownloadCompletionOnQueue:(dispatch_queue_t)queue callback:(void(^)(NSError *))callback;
@end

@interface RLMUser ()
- (std::shared_ptr<realm::SyncUser>)_syncUser;
@end

@interface TestNetworkTransport : RLMNetworkTransport
- (void)waitForCompletion;
@end
Expand Down Expand Up @@ -421,9 +418,11 @@ - (void)waitForDownloadsForRealm:(RLMRealm *)realm error:(NSError **)error {
}

- (void)setInvalidTokensForUser:(RLMUser *)user {
auto token = self.badAccessToken.UTF8String;
user._syncUser->log_out();
user._syncUser->log_in(token, token);
realm::RealmJWT token(std::string_view(self.badAccessToken));
user.user->update_data_for_testing([&](auto& data) {
data.access_token = token;
data.refresh_token = token;
});
}

- (void)writeToPartition:(NSString *)partition block:(void (^)(RLMRealm *))block {
Expand Down Expand Up @@ -554,15 +553,13 @@ - (void)resetAppCache {
[user logOutWithCompletion:^(NSError *) {
[ex fulfill];
}];

// Sessions are removed from the user asynchronously after a logout.
// We need to wait for this to happen before calling resetForTesting as
// that expects all sessions to be cleaned up first.
if (user.allSessions.count) {
[exs addObject:[self expectationForPredicate:[NSPredicate predicateWithFormat:@"allSessions.@count == 0"]
evaluatedWithObject:user handler:nil]];
}
}];

// Sessions are removed from the user asynchronously after a logout.
// We need to wait for this to happen before calling resetForTesting as
// that expects all sessions to be cleaned up first.
[exs addObject:[self expectationForPredicate:[NSPredicate predicateWithFormat:@"hasAnySessions = false"]
evaluatedWithObject:app.syncManager handler:nil]];
}

if (exs.count) {
Expand All @@ -578,8 +575,8 @@ - (void)resetAppCache {
[RLMApp resetAppCache];
}

- (NSString *)badAccessToken {
return @"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJl"
- (const char *)badAccessToken {
return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJl"
"eHAiOjE1ODE1MDc3OTYsImlhdCI6MTU4MTUwNTk5NiwiaXNzIjoiN"
"WU0M2RkY2M2MzZlZTEwNmVhYTEyYmRjIiwic3RpdGNoX2RldklkIjo"
"iMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic3RpdGNoX2RvbWFpbk"
Expand Down
6 changes: 6 additions & 0 deletions Realm/ObjectServerTests/SwiftObjectServerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,12 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
let ex = expectation(description: "Error callback should fire upon receiving an error")
ex.assertForOverFulfill = false // error handler can legally be called multiple times
app.syncManager.errorHandler = { @Sendable (error, _) in
// Connecting to sync with a deleted user sometimes triggers an
// internal server error instead of the desired error
if (error as NSError).code == SyncError.clientSessionError.rawValue && error.localizedDescription == "error" {
ex.fulfill()
return
}
assertSyncError(error, .clientUserError, "Unable to refresh the user access token: invalid session: failed to find refresh token")
ex.fulfill()
}
Expand Down
2 changes: 1 addition & 1 deletion Realm/RLMAPIKeyAuth.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ @implementation RLMAPIKeyAuth
return self.app._realmApp->provider_client<App::UserAPIKeyProviderClient>();
}

- (std::shared_ptr<realm::SyncUser>)currentUser {
- (std::shared_ptr<realm::app::User>)currentUser {
return self.app._realmApp->current_user();
}

Expand Down

0 comments on commit 2ea8d98

Please sign in to comment.