diff options
author | marinofaggiana <marino@marinofaggiana.com> | 2020-02-05 14:25:21 +0300 |
---|---|---|
committer | marinofaggiana <marino@marinofaggiana.com> | 2020-02-05 14:25:21 +0300 |
commit | d16225d79ed91d4e07476537b932d8e8eadd4de2 (patch) | |
tree | 089461486bfd015d2c937eb7e6e15a5580ac811d /Carthage | |
parent | 7ad8fcae881f006715ae218f234ebf1a94c9c507 (diff) |
Update DB - fix split view controller - onlyoffice useragent + fix
Diffstat (limited to 'Carthage')
51 files changed, 1435 insertions, 440 deletions
diff --git a/Carthage/Checkouts/CocoaLumberjack/.travis.yml b/Carthage/Checkouts/CocoaLumberjack/.travis.yml index ffa3446a1..9c73d2a9a 100644 --- a/Carthage/Checkouts/CocoaLumberjack/.travis.yml +++ b/Carthage/Checkouts/CocoaLumberjack/.travis.yml @@ -58,7 +58,6 @@ script: - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'watchOSSwiftIntegration' -configuration Release -sdk watchsimulator -destination 'platform=iOS Simulator,name=iPhone 11 Pro' | xcpretty -c
- echo "Run the tests"
- - xcodebuild test -skip-testing:'iOS Tests/DDFileLoggerPerformanceTests' -project Tests/Tests.xcodeproj -scheme 'iOS Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.3.1' GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
- xcodebuild test -skip-testing:'iOS Tests/DDFileLoggerPerformanceTests' -project Tests/Tests.xcodeproj -scheme 'iOS Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11 Pro,OS=latest' GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
- xcodebuild test -skip-testing:'OS X Tests/DDFileLoggerPerformanceTests' -project Tests/Tests.xcodeproj -scheme 'OS X Tests' -sdk macosx GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
diff --git a/Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md b/Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md index ec0009e14..9d6cf60bb 100644 --- a/Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md +++ b/Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md @@ -1,3 +1,17 @@ +## [3.6.1 - Xcode 11.3.1 on Jan 25th, 2020](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.6.1) + +### Public +- Improve error handling during log file creation in DDFileLogger & DDLogFileManager (#1103 / #1111) +- Improve nullability annotations in public headers (#1111 / #1112 / #1119) +- Added support for thread QOS in DDLogMessage class (#1124) + +### Internal +- Fix rolling timer being rescheduled rapidly due to leeway (#1106 / #1107) +- Fix -didArchiveLogFile: returning the file name instead of the file path (#1078) +- Fix setxattr() function usage (#1118) +- Fix NSDateFormatter thread safety (#1121) +- Fix -lt_dataForMessage: duplicated code (#1122) + ## [3.6.0 - Xcode 11 on October 2nd, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.6.0) ### Public diff --git a/Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec b/Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec index 0f04f1dda..c7e196c9a 100644 --- a/Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec +++ b/Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'CocoaLumberjack' - s.version = '3.6.0' + s.version = '3.6.1' s.license = 'BSD' s.summary = 'A fast & simple, yet powerful & flexible logging framework for Mac and iOS.' s.homepage = 'https://github.com/CocoaLumberjack/CocoaLumberjack' diff --git a/Carthage/Checkouts/realm-cocoa/.jenkins.yml b/Carthage/Checkouts/realm-cocoa/.jenkins.yml index 0097ef2ad..864ef1c25 100644 --- a/Carthage/Checkouts/realm-cocoa/.jenkins.yml +++ b/Carthage/Checkouts/realm-cocoa/.jenkins.yml @@ -6,10 +6,10 @@ xcode_version: - 10.0 - 10.1 - - 10.2.1 - 10.3 - 11.1 - - 11.2 + - 11.2.1 + - 11.3 target: - docs - swiftlint @@ -20,9 +20,11 @@ target: - ios-dynamic - watchos - tvos - - ios-swift - osx-swift + - ios-swift - tvos-swift + - catalyst + - catalyst-swift - cocoapods-osx - cocoapods-ios - cocoapods-ios-dynamic @@ -52,31 +54,31 @@ exclude: target: docs configuration: Release - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: docs configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: docs configuration: Release - - xcode_version: 10.3 + - xcode_version: 11.1 target: docs configuration: Debug - - xcode_version: 10.3 + - xcode_version: 11.1 target: docs configuration: Release - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: docs configuration: Debug - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: docs configuration: Release - - xcode_version: 11.2 + - xcode_version: 11.3 target: docs configuration: Debug @@ -96,31 +98,31 @@ exclude: target: swiftlint configuration: Release - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: swiftlint configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: swiftlint configuration: Release - - xcode_version: 10.3 + - xcode_version: 11.1 target: swiftlint configuration: Debug - - xcode_version: 10.3 + - xcode_version: 11.1 target: swiftlint configuration: Release - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: swiftlint configuration: Debug - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: swiftlint configuration: Release - - xcode_version: 11.2 + - xcode_version: 11.3 target: swiftlint configuration: Debug @@ -136,31 +138,31 @@ exclude: target: osx-encryption configuration: Release - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: osx-encryption configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: osx-encryption configuration: Release - - xcode_version: 10.3 + - xcode_version: 11.1 target: osx-encryption configuration: Debug - - xcode_version: 10.3 + - xcode_version: 11.1 target: osx-encryption configuration: Release - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: osx-encryption configuration: Debug - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: osx-encryption configuration: Release - - xcode_version: 11.2 + - xcode_version: 11.3 target: osx-encryption configuration: Debug @@ -176,31 +178,31 @@ exclude: target: osx-object-server configuration: Release - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: osx-object-server configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: osx-object-server configuration: Release - - xcode_version: 10.3 + - xcode_version: 11.1 target: osx-object-server configuration: Debug - - xcode_version: 10.3 + - xcode_version: 11.1 target: osx-object-server configuration: Release - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: osx-object-server configuration: Debug - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: osx-object-server configuration: Release - - xcode_version: 11.2 + - xcode_version: 11.3 target: osx-object-server configuration: Debug @@ -212,16 +214,36 @@ exclude: target: ios-static configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: ios-static + configuration: Release + + - xcode_version: 10.3 target: ios-static configuration: Debug - xcode_version: 10.3 target: ios-static + configuration: Release + + - xcode_version: 11.1 + target: ios-static configuration: Debug - xcode_version: 11.1 target: ios-static + configuration: Release + + - xcode_version: 11.2.1 + target: ios-static + configuration: Debug + + - xcode_version: 11.2.1 + target: ios-static + configuration: Release + + - xcode_version: 11.3 + target: ios-static configuration: Debug - xcode_version: 10.0 @@ -232,16 +254,36 @@ exclude: target: ios-dynamic configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: ios-dynamic + configuration: Release + + - xcode_version: 10.3 target: ios-dynamic configuration: Debug - xcode_version: 10.3 target: ios-dynamic + configuration: Release + + - xcode_version: 11.1 + target: ios-dynamic configuration: Debug - xcode_version: 11.1 target: ios-dynamic + configuration: Release + + - xcode_version: 11.2.1 + target: ios-dynamic + configuration: Debug + + - xcode_version: 11.2.1 + target: ios-dynamic + configuration: Release + + - xcode_version: 11.3 + target: ios-dynamic configuration: Debug - xcode_version: 10.0 @@ -252,16 +294,36 @@ exclude: target: watchos configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: watchos + configuration: Release + + - xcode_version: 10.3 target: watchos configuration: Debug - xcode_version: 10.3 target: watchos + configuration: Release + + - xcode_version: 11.1 + target: watchos configuration: Debug - xcode_version: 11.1 target: watchos + configuration: Release + + - xcode_version: 11.2.1 + target: watchos + configuration: Debug + + - xcode_version: 11.2.1 + target: watchos + configuration: Release + + - xcode_version: 11.3 + target: watchos configuration: Debug - xcode_version: 10.0 @@ -272,16 +334,36 @@ exclude: target: tvos configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: tvos + configuration: Release + + - xcode_version: 10.3 target: tvos configuration: Debug - xcode_version: 10.3 target: tvos + configuration: Release + + - xcode_version: 11.1 + target: tvos configuration: Debug - xcode_version: 11.1 target: tvos + configuration: Release + + - xcode_version: 11.2.1 + target: tvos + configuration: Debug + + - xcode_version: 11.2.1 + target: tvos + configuration: Release + + - xcode_version: 11.3 + target: tvos configuration: Debug - xcode_version: 10.0 @@ -292,67 +374,147 @@ exclude: target: ios-swift configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: ios-swift + configuration: Release + + - xcode_version: 10.3 target: ios-swift configuration: Debug - xcode_version: 10.3 target: ios-swift + configuration: Release + + - xcode_version: 11.1 + target: ios-swift configuration: Debug - xcode_version: 11.1 target: ios-swift + configuration: Release + + - xcode_version: 11.2.1 + target: ios-swift + configuration: Debug + + - xcode_version: 11.2.1 + target: ios-swift + configuration: Release + + - xcode_version: 11.3 + target: ios-swift configuration: Debug - xcode_version: 10.0 - target: osx-swift + target: tvos-swift configuration: Debug - xcode_version: 10.1 - target: osx-swift + target: tvos-swift configuration: Debug - - xcode_version: 10.2.1 - target: osx-swift - configuration: Debug + - xcode_version: 10.1 + target: tvos-swift + configuration: Release - xcode_version: 10.3 - target: osx-swift + target: tvos-swift configuration: Debug + - xcode_version: 10.3 + target: tvos-swift + configuration: Release + - xcode_version: 11.1 - target: osx-swift + target: tvos-swift configuration: Debug - - xcode_version: 10.0 + - xcode_version: 11.1 target: tvos-swift - configuration: Debug + configuration: Release - - xcode_version: 10.1 + - xcode_version: 11.2.1 target: tvos-swift configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 11.2.1 + target: tvos-swift + configuration: Release + + - xcode_version: 11.3 target: tvos-swift configuration: Debug + - xcode_version: 10.0 + target: catalyst + configuration: Debug + + - xcode_version: 10.0 + target: catalyst + configuration: Release + + - xcode_version: 10.1 + target: catalyst + configuration: Debug + + - xcode_version: 10.1 + target: catalyst + configuration: Release + - xcode_version: 10.3 - target: tvos-swift + target: catalyst configuration: Debug + - xcode_version: 10.3 + target: catalyst + configuration: Release + - xcode_version: 11.1 - target: tvos-swift + target: catalyst + configuration: Debug + + - xcode_version: 11.2.1 + target: catalyst configuration: Debug - xcode_version: 10.0 - target: cocoapods-osx + target: catalyst-swift + configuration: Debug + + - xcode_version: 10.0 + target: catalyst-swift + configuration: Release + + - xcode_version: 10.1 + target: catalyst-swift configuration: Debug - xcode_version: 10.1 + target: catalyst-swift + configuration: Release + + - xcode_version: 10.3 + target: catalyst-swift + configuration: Debug + + - xcode_version: 10.3 + target: catalyst-swift + configuration: Release + + - xcode_version: 11.1 + target: catalyst-swift + configuration: Debug + + - xcode_version: 11.2.1 + target: catalyst-swift + configuration: Debug + + - xcode_version: 10.0 target: cocoapods-osx configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 target: cocoapods-osx configuration: Debug @@ -364,7 +526,11 @@ exclude: target: cocoapods-osx configuration: Debug - - xcode_version: 11.2 + - xcode_version: 11.2.1 + target: cocoapods-osx + configuration: Debug + + - xcode_version: 11.3 target: cocoapods-osx configuration: Debug @@ -376,19 +542,35 @@ exclude: target: cocoapods-ios configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: cocoapods-ios + configuration: Release + + - xcode_version: 10.3 target: cocoapods-ios configuration: Debug - xcode_version: 10.3 target: cocoapods-ios + configuration: Release + + - xcode_version: 11.1 + target: cocoapods-ios configuration: Debug - xcode_version: 11.1 target: cocoapods-ios + configuration: Release + + - xcode_version: 11.2.1 + target: cocoapods-ios configuration: Debug - - xcode_version: 11.2 + - xcode_version: 11.2.1 + target: cocoapods-ios + configuration: Release + + - xcode_version: 11.3 target: cocoapods-ios configuration: Debug @@ -400,19 +582,35 @@ exclude: target: cocoapods-ios-dynamic configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: cocoapods-ios-dynamic + configuration: Release + + - xcode_version: 10.3 target: cocoapods-ios-dynamic configuration: Debug - xcode_version: 10.3 target: cocoapods-ios-dynamic + configuration: Release + + - xcode_version: 11.1 + target: cocoapods-ios-dynamic configuration: Debug - xcode_version: 11.1 target: cocoapods-ios-dynamic + configuration: Release + + - xcode_version: 11.2.1 + target: cocoapods-ios-dynamic configuration: Debug - - xcode_version: 11.2 + - xcode_version: 11.2.1 + target: cocoapods-ios-dynamic + configuration: Release + + - xcode_version: 11.3 target: cocoapods-ios-dynamic configuration: Debug @@ -424,19 +622,35 @@ exclude: target: cocoapods-watchos configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.1 + target: cocoapods-watchos + configuration: Release + + - xcode_version: 10.3 target: cocoapods-watchos configuration: Debug - xcode_version: 10.3 target: cocoapods-watchos + configuration: Release + + - xcode_version: 11.1 + target: cocoapods-watchos configuration: Debug - xcode_version: 11.1 target: cocoapods-watchos + configuration: Release + + - xcode_version: 11.2.1 + target: cocoapods-watchos configuration: Debug - - xcode_version: 11.2 + - xcode_version: 11.2.1 + target: cocoapods-watchos + configuration: Release + + - xcode_version: 11.3 target: cocoapods-watchos configuration: Debug @@ -456,27 +670,19 @@ exclude: target: swiftpm configuration: Release - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: swiftpm configuration: Debug - - xcode_version: 10.2.1 - target: swiftpm - configuration: Release - - xcode_version: 10.3 target: swiftpm - configuration: Debug + configuration: Release - xcode_version: 11.1 target: swiftpm configuration: Debug - - xcode_version: 11.1 - target: swiftpm - configuration: Release - - - xcode_version: 11.2 + - xcode_version: 11.2.1 target: swiftpm configuration: Debug @@ -496,31 +702,31 @@ exclude: target: swiftpm-address configuration: Release - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: swiftpm-address configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: swiftpm-address configuration: Release - - xcode_version: 10.3 + - xcode_version: 11.1 target: swiftpm-address configuration: Debug - - xcode_version: 10.3 + - xcode_version: 11.1 target: swiftpm-address configuration: Release - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: swiftpm-address configuration: Debug - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: swiftpm-address configuration: Release - - xcode_version: 11.2 + - xcode_version: 11.3 target: swiftpm-address configuration: Debug @@ -540,30 +746,30 @@ exclude: target: swiftpm-thread configuration: Release - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: swiftpm-thread configuration: Debug - - xcode_version: 10.2.1 + - xcode_version: 10.3 target: swiftpm-thread configuration: Release - - xcode_version: 10.3 + - xcode_version: 11.1 target: swiftpm-thread configuration: Debug - - xcode_version: 10.3 + - xcode_version: 11.1 target: swiftpm-thread configuration: Release - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: swiftpm-thread configuration: Debug - - xcode_version: 11.1 + - xcode_version: 11.2.1 target: swiftpm-thread configuration: Release - - xcode_version: 11.2 + - xcode_version: 11.3 target: swiftpm-thread configuration: Debug diff --git a/Carthage/Checkouts/realm-cocoa/CHANGELOG.md b/Carthage/Checkouts/realm-cocoa/CHANGELOG.md index a0052b131..e918effe7 100644 --- a/Carthage/Checkouts/realm-cocoa/CHANGELOG.md +++ b/Carthage/Checkouts/realm-cocoa/CHANGELOG.md @@ -1,3 +1,89 @@ +4.3.1 Release notes (2020-01-16) +============================================================= + +### Enhancements + +* Reduce the encrypted page reclaimer's impact on battery life when encryption + is used. ([Core #3461](https://github.com/realm/realm-core/pull/3461)). + +### Fixed + +* macOS binaries were built with the incorrect deployment target (10.14 rather + than 10.9), resulting in linker warnings. ([#6299](https://github.com/realm/realm-cocoa/issues/6299), since 3.18.0). +* An internal datastructure for List properties could be double-deleted if the + last reference was released from a thread other than the one which the List + was created on at the wrong time. This would typically manifest as + "pthread_mutex_destroy() failed", but could also result in other kinds of + crashes. ([#6333](https://github.com/realm/realm-cocoa/issues/6333)). +* Sorting on float or double properties containing NaN values had inconsistent + results and would sometimes crash due to out-of-bounds memory accesses. + ([#6357](https://github.com/realm/realm-cocoa/issues/6357)). +* A NOT query on a `List<Object>` which happened to have the objects in a + different order than the underlying table would sometimes include the object + immediately before an object which matches the query. ([#6289](https://github.com/realm/realm-cocoa/issues/6289), since 0.90.0). + +### Compatibility + +* File format: Generates Realms with format v9 (Reads and upgrades all previous formats) +* Realm Object Server: 3.21.0 or later. +* Carthage release for Swift is built with Xcode 11.3. + +### Internal + +* Upgraded realm-core from 5.23.6 to 5.23.8. +* Upgraded realm-sync from 4.9.0 to 4.9.4. + +4.3.0 Release notes (2019-12-19) +============================================================= + +### Enhancements + +* Add the ability to set a custom logger function on `RLMSyncManager` which is + called instead of the default NSLog-based logger. +* Expose configuration options for the various types of sync connection + timeouts and heartbeat intervals on `RLMSyncManager`. +* Add an option to have `Realm.asyncOpen()` report an error if the connection + times out rather than swallowing the error and attempting to reconnect until + it succeeds. + +### Fixed + +* Fix a crash when using value(forKey:) on a LinkingObjects property (including + when doing so indirectly, such as by querying on that property). + ([#6366](https://github.com/realm/realm-cocoa/issues/6366), since 4.0.0). +* Fix a rare crash in `ClientHistoryImpl::integrate_server_changesets()` which + would only happen in Debug builds (since v3.0.0). + +### Compatibility + +* File format: Generates Realms with format v9 (Reads and upgrades all previous formats) +* Realm Object Server: 3.21.0 or later. +* Carthage release for Swift is built with Xcode 11.3. + +### Internal + +* Upgraded realm-sync from 4.8.2 to 4.9.0. + +4.2.0 Release notes (2019-12-16) +============================================================= + +### Enhancements + +* Add `-[RLMRealm fileExistsForConfiguration:]`/`Realm.fileExists(for:)`, + which checks if a local Realm file exists for the given configuration. +* Add `-[RLMRealm deleteFilesForConfiguration:]`/`Realm.deleteFiles(for:)` + to delete the Realm file and all auxiliary files for the given configuration. + +### Fixed + +* None. + +### Compatibility + +* File format: Generates Realms with format v9 (Reads and upgrades all previous formats) +* Realm Object Server: 3.21.0 or later. +* Carthage release for Swift is built with Xcode 11.3. + 4.1.1 Release notes (2019-11-18) ============================================================= diff --git a/Carthage/Checkouts/realm-cocoa/Configuration/Base.xcconfig b/Carthage/Checkouts/realm-cocoa/Configuration/Base.xcconfig index f4266e6b7..4405fcd10 100644 --- a/Carthage/Checkouts/realm-cocoa/Configuration/Base.xcconfig +++ b/Carthage/Checkouts/realm-cocoa/Configuration/Base.xcconfig @@ -61,3 +61,5 @@ WATCHOS_DEPLOYMENT_TARGET = 2.0; TVOS_DEPLOYMENT_TARGET = 9.0; SWIFT_VERSION = 4.0; +TARGETED_DEVICE_FAMILY = 1,2,3,4; +SDKROOT = $(REALM_SDKROOT); diff --git a/Carthage/Checkouts/realm-cocoa/Configuration/Realm/Realm.xcconfig b/Carthage/Checkouts/realm-cocoa/Configuration/Realm/Realm.xcconfig index e293c34d2..38cc2fdca 100644 --- a/Carthage/Checkouts/realm-cocoa/Configuration/Realm/Realm.xcconfig +++ b/Carthage/Checkouts/realm-cocoa/Configuration/Realm/Realm.xcconfig @@ -28,7 +28,10 @@ LD_RUNPATH_SEARCH_PATHS[sdk=iphone*] = $(inherited) @executable_path/Frameworks LD_RUNPATH_SEARCH_PATHS[sdk=watch*] = $(inherited) @executable_path/Frameworks @loader_path/Frameworks; LD_RUNPATH_SEARCH_PATHS[sdk=appletv*] = $(inherited) @executable_path/Frameworks @loader_path/Frameworks; -REALM_PLATFORM_SUFFIX = $(PLATFORM_NAME); +REALM_PLATFORM_SUFFIX_ = $(PLATFORM_NAME); // Xcode 10 does not define SDK_VARIANT +REALM_PLATFORM_SUFFIX_macos = macosx; +REALM_PLATFORM_SUFFIX_iosmac = maccatalyst; +REALM_PLATFORM_SUFFIX = $(REALM_PLATFORM_SUFFIX_$(SDK_VARIANT)); OTHER_LDFLAGS[sdk=macosx*] = -lrealm-$(REALM_PLATFORM_SUFFIX)$(REALM_LIBRARY_SUFFIX) $(REALM_CATALYST_FLAGS); OTHER_LIBTOOLFLAGS[sdk=macosx*] = -lrealm-$(REALM_PLATFORM_SUFFIX)$(REALM_LIBRARY_SUFFIX) $(REALM_CATALYST_FLAGS); OTHER_LDFLAGS[sdk=iphone*] = -lrealm-ios$(REALM_LIBRARY_SUFFIX); diff --git a/Carthage/Checkouts/realm-cocoa/Configuration/TestHost.xcconfig b/Carthage/Checkouts/realm-cocoa/Configuration/TestHost.xcconfig index d8b905a3b..c8cc93fc3 100644 --- a/Carthage/Checkouts/realm-cocoa/Configuration/TestHost.xcconfig +++ b/Carthage/Checkouts/realm-cocoa/Configuration/TestHost.xcconfig @@ -11,9 +11,12 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; PRODUCT_BUNDLE_IDENTIFIER = io.realm.TestHost; +REALM_UI_FRAMEWORK_ = Cocoa; +REALM_UI_FRAMEWORK_uikit = UIKit; + OTHER_LDFLAGS[sdk=iphone*] = -framework UIKit; OTHER_LDFLAGS[sdk=appletv*] = -framework UIKit; -OTHER_LDFLAGS[sdk=macosx*] = -framework Cocoa; +OTHER_LDFLAGS[sdk=macosx*] = -framework $(REALM_UI_FRAMEWORK_$(RESOURCES_UI_FRAMEWORK_FAMILY)); PRINCIPAL_CLASS[sdk=iphone*] = UIApplication; PRINCIPAL_CLASS[sdk=appletv*] = UIApplication; diff --git a/Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability b/Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability index da57f86de..07889287b 100644 --- a/Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability +++ b/Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability @@ -1,10 +1,10 @@ -xcodeVersions = ['10.0', '10.1', '10.2.1', '10.3', '11.1', '11.2'] +xcodeVersions = ['10.0', '10.1', '10.3', '11.1', '11.2.1', '11.3'] platforms = ['osx', 'ios', 'watchos', 'tvos', 'catalyst'] carthagePlatforms = ['osx', 'ios', 'watchos', 'tvos'] platformNames = ['osx': 'macOS', 'ios': 'iOS', 'watchos': 'watchOS', 'tvos': 'tvOS', 'catalyst': 'Catalyst'] -carthageXcodeVersion = '11.2' +carthageXcodeVersion = '11.3' objcXcodeVersion = '10.1' -docsSwiftVersion = '5.1' +docsSwiftVersion = '5.1.2' def installationTest(platform, test, language) { return { @@ -65,6 +65,7 @@ def doBuild() { unstash 'source' sh """ export REALM_SWIFT_VERSION=${docsSwiftVersion} + export PATH='/Users/realm/.rbenv/bin:/Users/realm/.rbenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/realm/.gems/bin' ./scripts/reset-simulators.sh ./build.sh docs cd docs diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm index 17ed01203..fc403b9ac 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm @@ -219,10 +219,11 @@ __block XCTestExpectation *ex; [RLMSyncSessionRefreshHandle calculateFireDateUsingTestLogic:YES blockOnRefreshCompletion:^(BOOL success) { - XCTAssertTrue(success); - refreshCount++; - [ex fulfill]; - }]; + XCTAssertTrue(success); + if (refreshCount++ == 3) { // arbitrary choice; refreshes every second + [ex fulfill]; + } + }]; // Open the Realm. NSURL *url = REALM_URL(); RLMSyncUser *user = [self logInUserForCredentials:[RLMObjectServerTests basicCredentialsWithName:NSStringFromSelector(_cmd) @@ -232,7 +233,91 @@ ex = [self expectationWithDescription:@"Timer fired"]; [self waitForExpectationsWithTimeout:10 handler:nil]; XCTAssertTrue(errorCount == 0); - XCTAssertTrue(refreshCount > 0); + XCTAssertTrue(refreshCount >= 4); +} + +- (void)testLoginConnectionTimeoutFromManager { + // First create the user, talking directly to ROS + NSString *userName = NSStringFromSelector(_cmd); + @autoreleasepool { + RLMSyncCredentials *credentials = [RLMObjectServerTests basicCredentialsWithName:userName register:YES]; + RLMSyncUser *user = [self logInUserForCredentials:credentials server:[NSURL URLWithString:@"http://127.0.0.1:9080"]]; + [user logOut]; + } + + RLMSyncTimeoutOptions *timeoutOptions = [RLMSyncTimeoutOptions new]; + + // 9082 is a proxy which delays responding to requests + NSURL *authURL = [NSURL URLWithString:@"http://127.0.0.1:9082"]; + + // Login attempt should time out + timeoutOptions.connectTimeout = 1000.0; + RLMSyncManager.sharedManager.timeoutOptions = timeoutOptions; + + RLMSyncCredentials *credentials = [RLMObjectServerTests basicCredentialsWithName:userName register:NO]; + XCTestExpectation *ex = [self expectationWithDescription:@"Login should time out"]; + [RLMSyncUser logInWithCredentials:credentials authServerURL:authURL + onCompletion:^(RLMSyncUser *user, NSError *error) { + XCTAssertNil(user); + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.domain, NSURLErrorDomain); + XCTAssertEqual(error.code, NSURLErrorTimedOut); + [ex fulfill]; + }]; + [self waitForExpectationsWithTimeout:2.0 handler:nil]; + + // Login attempt should succeeed + timeoutOptions.connectTimeout = 3000.0; + RLMSyncManager.sharedManager.timeoutOptions = timeoutOptions; + + ex = [self expectationWithDescription:@"Login should succeed"]; + [RLMSyncUser logInWithCredentials:credentials authServerURL:authURL + onCompletion:^(RLMSyncUser *user, NSError *error) { + [user logOut]; + XCTAssertNotNil(user); + XCTAssertNil(error); + [ex fulfill]; + }]; + [self waitForExpectationsWithTimeout:3.0 handler:nil]; +} + +- (void)testLoginConnectionTimeoutDirect { + // First create the user, talking directly to ROS + NSString *userName = NSStringFromSelector(_cmd); + @autoreleasepool { + RLMSyncCredentials *credentials = [RLMObjectServerTests basicCredentialsWithName:userName register:YES]; + RLMSyncUser *user = [self logInUserForCredentials:credentials server:[NSURL URLWithString:@"http://127.0.0.1:9080"]]; + [user logOut]; + } + + // 9082 is a proxy which delays responding to requests + NSURL *authURL = [NSURL URLWithString:@"http://127.0.0.1:9082"]; + + // Login attempt should time out + RLMSyncCredentials *credentials = [RLMObjectServerTests basicCredentialsWithName:userName register:NO]; + XCTestExpectation *ex = [self expectationWithDescription:@"Login should time out"]; + [RLMSyncUser logInWithCredentials:credentials authServerURL:authURL + timeout:1.0 callbackQueue:dispatch_get_main_queue() + onCompletion:^(RLMSyncUser *user, NSError *error) { + XCTAssertNil(user); + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.domain, NSURLErrorDomain); + XCTAssertEqual(error.code, NSURLErrorTimedOut); + [ex fulfill]; + }]; + [self waitForExpectationsWithTimeout:2.0 handler:nil]; + + // Login attempt should succeeed + ex = [self expectationWithDescription:@"Login should succeed"]; + [RLMSyncUser logInWithCredentials:credentials authServerURL:authURL + timeout:3.0 callbackQueue:dispatch_get_main_queue() + onCompletion:^(RLMSyncUser *user, NSError *error) { + [user logOut]; + XCTAssertNotNil(user); + XCTAssertNil(error); + [ex fulfill]; + }]; + [self waitForExpectationsWithTimeout:3.0 handler:nil]; } #pragma mark - Users @@ -1662,6 +1747,34 @@ static const NSInteger NUMBER_OF_BIG_OBJECTS = 2; [self waitForExpectationsWithTimeout:2.0 handler:nil]; } +- (void)testAsyncOpenConnectionTimeout { + NSString *userName = NSStringFromSelector(_cmd); + // 9083 is a proxy which delays responding to requests + NSURL *authURL = [NSURL URLWithString:@"http://127.0.0.1:9083"]; + RLMSyncUser *user = [self logInUserForCredentials:[RLMObjectServerTests basicCredentialsWithName:userName register:YES] + server:authURL]; + RLMRealmConfiguration *c = [user configuration]; + RLMSyncConfiguration *syncConfig = c.syncConfiguration; + syncConfig.cancelAsyncOpenOnNonFatalErrors = true; + c.syncConfiguration = syncConfig; + + RLMSyncTimeoutOptions *timeoutOptions = [RLMSyncTimeoutOptions new]; + timeoutOptions.connectTimeout = 1000.0; + RLMSyncManager.sharedManager.timeoutOptions = timeoutOptions; + + XCTestExpectation *ex = [self expectationWithDescription:@"async open"]; + [RLMRealm asyncOpenWithConfiguration:c + callbackQueue:dispatch_get_main_queue() + callback:^(RLMRealm *realm, NSError *error) { + XCTAssertNotNil(error); + XCTAssertEqual(error.code, ETIMEDOUT); + XCTAssertEqual(error.domain, NSPOSIXErrorDomain); + XCTAssertNil(realm); + [ex fulfill]; + }]; + [self waitForExpectationsWithTimeout:10.0 handler:nil]; +} + #pragma mark - Compact on Launch - (void)testCompactOnLaunch { @@ -2150,8 +2263,6 @@ static NSURL *certificateURL(NSString *filename) { } - (void)verifyOpenFails:(RLMRealmConfiguration *)config { - [self openRealmWithConfiguration:config]; - XCTestExpectation *expectation = [self expectationWithDescription:@"wait for error"]; RLMSyncManager.sharedManager.errorHandler = ^(NSError *error, __unused RLMSyncSession *session) { XCTAssertTrue([error.domain isEqualToString:RLMSyncErrorDomain]); @@ -2159,6 +2270,7 @@ static NSURL *certificateURL(NSString *filename) { [expectation fulfill]; }; + [self openRealmWithConfiguration:config]; [self waitForExpectationsWithTimeout:20.0 handler:nil]; } diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncManager+ObjectServerTests.h b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncManager+ObjectServerTests.h deleted file mode 100644 index cf914be0a..000000000 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncManager+ObjectServerTests.h +++ /dev/null @@ -1,25 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// - -#import "RLMSyncManager.h" - -@interface RLMSyncManager (ObjectServerTests) - -- (void)prepareForDestruction; - -@end diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncManager+ObjectServerTests.m b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncManager+ObjectServerTests.m deleted file mode 100644 index 46746c8df..000000000 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncManager+ObjectServerTests.m +++ /dev/null @@ -1,44 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// - -#import "RLMSyncManager_Private.h" -#import "RLMSyncManager+ObjectServerTests.h" -#import "RLMSyncTestCase.h" -#import "RLMTestUtils.h" - -@interface RLMSyncManager () -- (NSArray<RLMSyncUser *> *)_allUsers; -@end - -@implementation RLMSyncManager (ObjectServerTests) - -+ (void)load { - RLMSwapOutClassMethod(self, @selector(sharedManager), @selector(ost_sharedManager)); -} - -+ (instancetype)ost_sharedManager { - return [RLMSyncTestCase managerForCurrentTest]; -} - -- (void)prepareForDestruction { - // Log out all the logged-in users. - [[self _allUsers] makeObjectsPerformSelector:@selector(logOut)]; - [RLMSyncManager resetForTesting]; -} - -@end diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.h b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.h index 1723c51c9..42a23fbdc 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.h +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.h @@ -24,7 +24,7 @@ typedef void(^RLMSyncBasicErrorReportingBlock)(NSError * _Nullable); NS_ASSUME_NONNULL_BEGIN @interface RLMSyncManager () -- (void)setSessionCompletionNotifier:(RLMSyncBasicErrorReportingBlock)sessionCompletionNotifier; +- (void)setSessionCompletionNotifier:(nullable RLMSyncBasicErrorReportingBlock)sessionCompletionNotifier; @end @interface SyncObject : RLMObject @@ -38,8 +38,6 @@ NS_ASSUME_NONNULL_BEGIN @interface RLMSyncTestCase : RLMMultiProcessTestCase -+ (RLMSyncManager *)managerForCurrentTest; - + (NSURL *)authServerURL; + (NSURL *)secureAuthServerURL; @@ -125,6 +123,9 @@ NS_ASSUME_NONNULL_BEGIN /// Manually set the refresh token for a user. Used for testing invalid token conditions. - (void)manuallySetRefreshTokenForUser:(RLMSyncUser *)user value:(NSString *)tokenValue; +- (void)setupSyncManager; +- (void)resetSyncManager; + @end NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.mm b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.mm index f78648425..d114d0597 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.mm @@ -24,7 +24,7 @@ #import "RLMRealm_Dynamic.h" #import "RLMRealm_Private.hpp" #import "RLMRealmConfiguration_Private.h" -#import "RLMSyncManager+ObjectServerTests.h" +#import "RLMSyncManager_Private.h" #import "RLMSyncSessionRefreshHandle+ObjectServerTests.h" #import "RLMSyncConfiguration_Private.h" #import "RLMUtil.hpp" @@ -53,7 +53,8 @@ static NSString *nodePath() { @interface RLMSyncManager () + (void)_setCustomBundleID:(NSString *)customBundleID; -- (instancetype)initWithCustomRootDirectory:(NSURL *)rootDirectory; +- (void)configureWithRootDirectory:(NSURL *)rootDirectory; +- (NSArray<RLMSyncUser *> *)_allUsers; @end @interface RLMSyncTestCase () @@ -90,7 +91,6 @@ static NSString *nodePath() { @end static NSTask *s_task; -static RLMSyncManager *s_managerForTest; static NSURL *syncDirectoryForChildProcess() { NSString *path = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)[0]; @@ -240,10 +240,6 @@ static NSURL *syncDirectoryForChildProcess() { @implementation RLMSyncTestCase -+ (RLMSyncManager *)managerForCurrentTest { - return s_managerForTest; -} - #pragma mark - Helper methods - (BOOL)isPartial { @@ -323,6 +319,7 @@ static NSURL *syncDirectoryForChildProcess() { // Wait for login to succeed or fail. XCTAssert(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC))) == 0, @"Timed out while trying to asynchronously open Realm for URL: %@", url); + RLMSyncManager.sharedManager.sessionCompletionNotifier = nil; return realm; } @@ -512,6 +509,19 @@ static NSURL *syncDirectoryForChildProcess() { - (void)setUp { [super setUp]; self.continueAfterFailure = NO; + + REALM_ASSERT(RLMSyncManager.sharedManager._allUsers.count == 0); + [RLMSyncManager resetForTesting]; + + [self setupSyncManager]; +} + +- (void)tearDown { + [self resetSyncManager]; + [super tearDown]; +} + +- (void)setupSyncManager { NSURL *clientDataRoot; if (self.isParent) { [RealmObjectServer.sharedServer launch]; @@ -520,21 +530,21 @@ static NSURL *syncDirectoryForChildProcess() { else { clientDataRoot = syncDirectoryForChildProcess(); } + NSError *error; [NSFileManager.defaultManager removeItemAtURL:clientDataRoot error:&error]; [NSFileManager.defaultManager createDirectoryAtURL:clientDataRoot withIntermediateDirectories:YES attributes:nil error:&error]; - s_managerForTest = [[RLMSyncManager alloc] initWithCustomRootDirectory:clientDataRoot]; - [RLMSyncManager sharedManager].logLevel = RLMSyncLogLevelOff; - [RLMSyncManager sharedManager].userAgent = self.name; + RLMSyncManager *syncManager = RLMSyncManager.sharedManager; + [syncManager configureWithRootDirectory:clientDataRoot]; + syncManager.logLevel = RLMSyncLogLevelOff; + syncManager.userAgent = self.name; } -- (void)tearDown { - [s_managerForTest prepareForDestruction]; - s_managerForTest = nil; +- (void)resetSyncManager { + [RLMSyncManager.sharedManager._allUsers makeObjectsPerformSelector:@selector(logOut)]; + [RLMSyncManager resetForTesting]; [RLMSyncSessionRefreshHandle calculateFireDateUsingTestLogic:NO blockOnRefreshCompletion:nil]; - - [super tearDown]; } @end diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift index 1730850ce..24ae51d26 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift @@ -354,6 +354,48 @@ class SwiftObjectServerTests: SwiftSyncTestCase { waitForExpectations(timeout: 10.0, handler: nil) } + func testAsyncOpenTimeout() { + let syncTimeoutOptions = SyncTimeoutOptions() + syncTimeoutOptions.connectTimeout = 3000 + SyncManager.shared.timeoutOptions = syncTimeoutOptions + + // The server proxy adds a 2 second delay, so a 3 second timeout should succeed + autoreleasepool { + let user = try! synchronouslyLogInUser(for: basicCredentials(register: true), server: slowConnectAuthURL) + let config = user.configuration(cancelAsyncOpenOnNonFatalErrors: true) + let ex = expectation(description: "async open") + Realm.asyncOpen(configuration: config) { _, error in + XCTAssertNil(error) + ex.fulfill() + } + waitForExpectations(timeout: 10.0, handler: nil) + user.logOut() + } + + self.resetSyncManager() + self.setupSyncManager() + + // and a 1 second timeout should fail + autoreleasepool { + let user = try! synchronouslyLogInUser(for: basicCredentials(register: true), server: slowConnectAuthURL) + let config = user.configuration(cancelAsyncOpenOnNonFatalErrors: true) + + syncTimeoutOptions.connectTimeout = 1000 + SyncManager.shared.timeoutOptions = syncTimeoutOptions + + let ex = expectation(description: "async open") + Realm.asyncOpen(configuration: config) { _, error in + XCTAssertNotNil(error) + if let error = error as NSError? { + XCTAssertEqual(error.code, Int(ETIMEDOUT)) + XCTAssertEqual(error.domain, NSPOSIXErrorDomain) + } + ex.fulfill() + } + waitForExpectations(timeout: 4.0, handler: nil) + } + } + // MARK: - Administration func testRetrieveUserInfo() { diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftSyncTestCase.swift b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftSyncTestCase.swift index a258dd71c..6c5208d0f 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftSyncTestCase.swift +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftSyncTestCase.swift @@ -73,6 +73,7 @@ class SwiftSyncTestCase: RLMSyncTestCase { var task: Process? let authURL: URL = URL(string: "http://127.0.0.1:9080")! + let slowConnectAuthURL: URL = URL(string: "http://127.0.0.1:9083")! let realmURL: URL = URL(string: "realm://127.0.0.1:9080/~/testBasicSync")! /// For testing, make a unique Realm URL of the form "realm://127.0.0.1:9080/~/X", @@ -110,6 +111,7 @@ class SwiftSyncTestCase: RLMSyncTestCase { SyncManager.shared.setSessionCompletionNotifier(basicBlock) let realm = try Realm(configuration: configuration) let result = semaphore.wait(timeout: .now() + DispatchTimeInterval.seconds(20)) + SyncManager.shared.setSessionCompletionNotifier(nil) XCTAssertEqual(result, .success) return realm } diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js index 84e55958b..639357c50 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js @@ -48,29 +48,17 @@ class PasswordEmailHandler { } } -// A simple proxy server that runs in front of ROS and validates custom headers -class HeaderValidationProxy { +class Proxy { constructor(listenPort, targetPort) { this.proxy = httpProxy.createProxyServer({target: `http://127.0.0.1:${targetPort}`, ws: true}); this.proxy.on('error', e => { console.log('proxy error', e); }); this.server = http.createServer((req, res) => { - if (this.validate(req)) { - this.proxy.web(req, res); - } - else { - res.writeHead(400); - res.end('Missing X-Allow-Connection header'); - } + this.web(req, res); }); this.server.on('upgrade', (req, socket, head) => { - if (this.validate(req)) { - this.proxy.ws(req, socket, head); - } - else { - socket.end('HTTP/1.1 400 Bad Request\r\n\r\n'); - } + this.ws(req, socket, head); }); this.server.listen(listenPort); } @@ -80,11 +68,50 @@ class HeaderValidationProxy { this.proxy.close(); } + web(req, res) { + this.proxy.web(req, res); + } + + ws(req, socket, head) { + this.proxy.ws(req, socket, head); + } +} + +// A simple proxy server that runs in front of ROS and validates custom headers +class HeaderValidationProxy extends Proxy { + web(req, res) { + if (this.validate(req)) { + this.proxy.web(req, res); + } + else { + res.writeHead(400); + res.end('Missing X-Allow-Connection header'); + } + } + ws(req, socket, head) { + if (this.validate(req)) { + this.proxy.ws(req, socket, head); + } + else { + socket.end('HTTP/1.1 400 Bad Request\r\n\r\n'); + } + } validate(req) { return !!req.headers['x-allow-connection']; } } +// A proxy which sits in front of ROS and takes a long time to establish connections +class SlowConnectingWebProxy extends Proxy { + web(req, res) { + setTimeout(() => this.proxy.web(req, res), 2000); + } +} +class SlowConnectingWsProxy extends Proxy { + ws(req, socket, head) { + setTimeout(() => this.proxy.ws(req, socket, head), 2000); + } +} const server = new ROS.BasicServer(); server.start({ @@ -125,3 +152,5 @@ server.start({ console.error(`Error starting Realm Object Server: ${err.message}`) }); new HeaderValidationProxy(9081, 9080); +new SlowConnectingWebProxy(9082, 9080); +new SlowConnectingWsProxy(9083, 9080); diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list index 46ec3efd7..bc76f1f92 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list @@ -1,4 +1,4 @@ -REALM_CORE_VERSION=5.23.5 -REALM_SYNC_VERSION=4.7.8 +REALM_CORE_VERSION=5.23.6 +REALM_SYNC_VERSION=4.9.0 ANDROID_OPENSSL_VERSION=1.0.2k REALM_CORE_PACKAGING=2 diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/CMakeLists.txt b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/CMakeLists.txt index 95110e9c5..d16398a70 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/CMakeLists.txt +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/CMakeLists.txt @@ -52,6 +52,12 @@ endif() add_executable(tests ${SOURCES} ${HEADERS}) target_compile_definitions(tests PRIVATE ${PLATFORM_DEFINES}) +if(VSCODE_TEST_RUNNER) + # Increase the Catch2 virtual console width so that the Visual Studio Code + # Test Explorer extension can parse long test names + target_compile_definitions(tests PRIVATE -DCATCH_CONFIG_CONSOLE_WIDTH=300) +endif() + if(REALM_ENABLE_SYNC) # It's necessary to explicitly link to realm-sync here to control the order in which libraries are # linked to avoid link errors when using GNU ld. diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp index 12c5126fa..244ad13e8 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp @@ -461,8 +461,7 @@ TEST_CASE("Get Realm using Async Open", "[asyncOpen]") { if (!util::EventLoop::has_implementation()) return; - auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); }); - SyncManager::shared().configure(tmp_dir(), SyncManager::MetadataMode::NoEncryption); + TestSyncManager init_sync_manager; SyncServer server; SyncTestFile config(server, "default"); diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.cpp b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.cpp index 29d0d3ee3..7eb7d72a1 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.cpp +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.cpp @@ -18,6 +18,8 @@ #include "util/test_file.hpp" +#include "test_utils.hpp" + #include "impl/realm_coordinator.hpp" #if REALM_ENABLE_SYNC @@ -219,6 +221,28 @@ void wait_for_download(Realm& realm) wait_for_session(realm, &SyncSession::wait_for_download_completion); } +TestSyncManager::TestSyncManager(std::string const& base_path, SyncManager::MetadataMode mode) +{ + configure(base_path, mode); +} + +TestSyncManager::~TestSyncManager() +{ + SyncManager::shared().reset_for_testing(); +} + +void TestSyncManager::configure(std::string const& base_path, SyncManager::MetadataMode mode) +{ + SyncClientConfig config; + config.base_file_path = base_path.empty() ? tmp_dir() : base_path; + config.metadata_mode = mode; +#if TEST_ENABLE_SYNC_LOGGING + config.log_level = util::Logger::Level::all; +#else + config.log_level = util::Logger::Level::off; +#endif + SyncManager::shared().configure(config); +} #endif // REALM_ENABLE_SYNC diff --git a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.hpp b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.hpp index 463e199f4..d435b0b83 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.hpp +++ b/Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/util/test_file.hpp @@ -133,6 +133,12 @@ struct SyncTestFile : TestFile { std::string user_name="test"); }; +struct TestSyncManager { + TestSyncManager(std::string const& base_path="", realm::SyncManager::MetadataMode = realm::SyncManager::MetadataMode::NoEncryption); + ~TestSyncManager(); + static void configure(std::string const& base_path, realm::SyncManager::MetadataMode); +}; + void wait_for_upload(realm::Realm& realm); void wait_for_download(realm::Realm& realm); diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMConstants.h b/Carthage/Checkouts/realm-cocoa/Realm/RLMConstants.h index b96dacbfa..c4c109317 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMConstants.h +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMConstants.h @@ -161,6 +161,10 @@ typedef RLM_ERROR_ENUM(NSInteger, RLMError, RLMErrorDomain) { If you wish to migrate any data from the backup Realm, you can open it using the provided Realm configuration. */ RLMErrorIncompatibleSyncedFile = 11, + /** + Denotates an error where an operation was requested which cannot be performed on an open file. + */ + RLMErrorAlreadyOpen = 12, }; #pragma mark - Constants diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMNetworkClient.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMNetworkClient.mm index 5cb313547..009795ecf 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMNetworkClient.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMNetworkClient.mm @@ -42,8 +42,6 @@ static NSRange rangeForErrorType(RLMServerHTTPErrorCodeType type) { return NSMakeRange(type*100, kHTTPCodeRange); } -static std::atomic<NSTimeInterval> g_defaultTimeout{60.0}; - #pragma mark Network client @interface RLMSessionDelegate <NSURLSessionDelegate> : NSObject @@ -71,7 +69,7 @@ static std::atomic<NSTimeInterval> g_defaultTimeout{60.0}; + (void)sendRequestToServer:(NSURL *)serverURL JSON:(NSDictionary *)jsonDictionary completion:(void (^)(NSError *))completionBlock { - [self sendRequestToServer:serverURL JSON:jsonDictionary timeout:g_defaultTimeout.load() + [self sendRequestToServer:serverURL JSON:jsonDictionary timeout:0 completion:^(NSError *error, NSDictionary *) { completionBlock(error); }]; @@ -80,6 +78,14 @@ static std::atomic<NSTimeInterval> g_defaultTimeout{60.0}; JSON:(NSDictionary *)jsonDictionary timeout:(NSTimeInterval)timeout completion:(void (^)(NSError *, NSDictionary *))completionBlock { + // If the timeout isn't set then use the timeout set on the sync manager, + // or 60 seconds if it isn't set there either. + RLMSyncManager *syncManager = RLMSyncManager.sharedManager; + if (timeout < 1) + timeout = syncManager.timeoutOptions.connectTimeout / 1000.0; + if (timeout < 1) + timeout = 60.0; + // Create the request NSError *localError = nil; NSURL *requestURL = [self urlForAuthServer:serverURL payload:jsonDictionary]; @@ -92,8 +98,8 @@ static std::atomic<NSTimeInterval> g_defaultTimeout{60.0}; return; } } - request.timeoutInterval = MAX(timeout, 10); - RLMNetworkRequestOptions *options = RLMSyncManager.sharedManager.networkRequestOptions; + request.timeoutInterval = timeout; + RLMNetworkRequestOptions *options = syncManager.networkRequestOptions; NSDictionary<NSString *, NSString *> *headers = [self httpHeadersForPayload:jsonDictionary options:options]; for (NSString *key in headers) { [request addValue:headers[key] forHTTPHeaderField:key]; diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMObjectBase.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMObjectBase.mm index 4a49201a5..3b264c8d9 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMObjectBase.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMObjectBase.mm @@ -180,7 +180,11 @@ id RLMCreateManagedAccessor(Class cls, RLMClassInfo *info) { // Generic Swift properties can't be dynamic, so KVO doesn't work for them by default - (id)valueForUndefinedKey:(NSString *)key { - if (Ivar ivar = _objectSchema[key].swiftIvar) { + RLMProperty *prop = _objectSchema[key]; + if (Class accessor = prop.swiftAccessor) { + return [accessor get:(char *)(__bridge void *)self + ivar_getOffset(prop.swiftIvar)]; + } + if (Ivar ivar = prop.swiftIvar) { return RLMCoerceToNil(object_getIvar(self, ivar)); } return [super valueForUndefinedKey:key]; diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMPlatform.h.in b/Carthage/Checkouts/realm-cocoa/Realm/RLMPlatform.h.in index 249173393..2a0607e7e 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMPlatform.h.in +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMPlatform.h.in @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -#ifdef REALM_BUILDING_FOR_MACOSX +#ifdef REALM_BUILDING_FOR_MACOS #if !__is_target_os(macosx) #error Attempting to use Realm''s macOS framework in a non-macOS target. #endif diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.h b/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.h index 53212c030..cbc99cea7 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.h +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.h @@ -149,6 +149,61 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, readonly) BOOL isEmpty; +#pragma mark - File Management + +/** + Writes a compacted and optionally encrypted copy of the Realm to the given local URL. + + The destination file cannot already exist. + + Note that if this method is called from within a write transaction, the + *current* data is written, not the data from the point when the previous write + transaction was committed. + + @param fileURL Local URL to save the Realm to. + @param key Optional 64-byte encryption key to encrypt the new file with. + @param error If an error occurs, upon return contains an `NSError` object + that describes the problem. If you are not interested in + possible errors, pass in `NULL`. + + @return `YES` if the Realm was successfully written to disk, `NO` if an error occurred. + */ +- (BOOL)writeCopyToURL:(NSURL *)fileURL encryptionKey:(nullable NSData *)key error:(NSError **)error; + +/** + Checks if the Realm file for the given configuration exists locally on disk. + + For non-synchronized, non-in-memory Realms, this is equivalent to + `-[NSFileManager.defaultManager fileExistsAtPath:config.path]`. For + synchronized Realms, it takes care of computing the actual path on disk based + on the server, virtual path, and user as is done when opening the Realm. + + @param config A Realm configuration to check the existence of. + @return YES if the Realm file for the given configuration exists on disk, NO otherwise. + */ ++ (BOOL)fileExistsForConfiguration:(RLMRealmConfiguration *)config; + +/** + Deletes the local Realm file and associated temporary files for the given configuration. + + This deletes the ".realm", ".note" and ".management" files which would be + created by opening the Realm with the given configuration. It does not delete + the ".lock" file (which contains no persisted data and is recreated from + scratch every time the Realm file is opened). + + The Realm must not be currently open on any thread or in another process. If + it is, this will return NO and report the error RLMErrorAlreadyOpen. Attempting to open + the Realm on another thread while the deletion is happening will block (and + then create a new Realm and open that afterwards). + + If the Realm already does not exist this will return `NO` and report the error NSFileNoSuchFileError; + + @param config A Realm configuration identifying the Realm to be deleted. + @return YES if any files were deleted, NO otherwise. + */ ++ (BOOL)deleteFilesForConfiguration:(RLMRealmConfiguration *)config error:(NSError **)error + __attribute__((swift_error(nonnull_error))); + #pragma mark - Notifications /** @@ -189,9 +244,6 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea */ - (RLMNotificationToken *)addNotificationBlock:(RLMNotificationBlock)block __attribute__((warn_unused_result)); -#pragma mark - Transactions - - #pragma mark - Writing to a Realm /** @@ -426,25 +478,6 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea @property (nonatomic) BOOL autorefresh; /** - Writes a compacted and optionally encrypted copy of the Realm to the given local URL. - - The destination file cannot already exist. - - Note that if this method is called from within a write transaction, the - *current* data is written, not the data from the point when the previous write - transaction was committed. - - @param fileURL Local URL to save the Realm to. - @param key Optional 64-byte encryption key to encrypt the new file with. - @param error If an error occurs, upon return contains an `NSError` object - that describes the problem. If you are not interested in - possible errors, pass in `NULL`. - - @return `YES` if the Realm was successfully written to disk, `NO` if an error occurred. -*/ -- (BOOL)writeCopyToURL:(NSURL *)fileURL encryptionKey:(nullable NSData *)key error:(NSError **)error; - -/** Invalidates all `RLMObject`s, `RLMResults`, `RLMLinkingObjects`, and `RLMArray`s managed by the Realm. A Realm holds a read lock on the version of the data accessed by it, so diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.mm index 50bde2f0d..2ec9b2b58 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.mm @@ -928,6 +928,44 @@ REALM_NOINLINE static void translateSharedGroupOpenException(RLMRealmConfigurati return NO; } ++ (BOOL)fileExistsForConfiguration:(RLMRealmConfiguration *)config { + return [NSFileManager.defaultManager fileExistsAtPath:config.pathOnDisk]; +} + ++ (BOOL)deleteFilesForConfiguration:(RLMRealmConfiguration *)config error:(NSError **)error { + auto& path = config.config.path; + bool anyDeleted = false; + NSError *localError; + bool didCall = SharedGroup::call_with_lock(path, [&](auto const& path) { + NSURL *url = [NSURL fileURLWithPath:@(path.c_str())]; + NSFileManager *fm = NSFileManager.defaultManager; + + anyDeleted = [fm removeItemAtURL:url error:&localError]; + if (localError && localError.code != NSFileNoSuchFileError) { + return; + } + + [fm removeItemAtURL:[url URLByAppendingPathExtension:@"management"] error:&localError]; + if (localError && localError.code != NSFileNoSuchFileError) { + return; + } + + [fm removeItemAtURL:[url URLByAppendingPathExtension:@"note"] error:&localError]; + }); + if (error && localError && localError.code != NSFileNoSuchFileError) { + *error = localError; + } + else if (!didCall) { + if (error) { + NSString *msg = [NSString stringWithFormat:@"Realm file at path %s cannot be deleted because it is currently opened.", path.c_str()]; + *error = [NSError errorWithDomain:RLMErrorDomain + code:RLMErrorAlreadyOpen + userInfo:@{NSLocalizedDescriptionKey: msg}]; + } + } + return anyDeleted; +} + #if REALM_ENABLE_SYNC using Privilege = realm::ComputedPrivileges; static bool hasPrivilege(realm::ComputedPrivileges actual, realm::ComputedPrivileges expected) { diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.h b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.h index e31018c2d..5a74db21a 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.h +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.h @@ -85,6 +85,15 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, nullable, copy) NSString *urlPrefix; +/** + Whether nonfatal connection errors should cancel async opens. + + By default, if a nonfatal connection error such as a connection timing out occurs, any currently pending asyncOpen operations will ignore the error and continue to retry until it succeeds. If this is set to true, the open will instead fail and report the error. + + FIXME: This should probably be true by default in the next major version. + */ +@property (nonatomic) bool cancelAsyncOpenOnNonFatalErrors; + /// :nodoc: - (instancetype)initWithUser:(RLMSyncUser *)user realmURL:(NSURL *)url __attribute__((unavailable("Use [RLMSyncUser configurationWithURL:] instead"))); diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.mm index aaa75b30f..b082477c4 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration.mm @@ -68,8 +68,7 @@ BOOL isValidRealmURL(NSURL *url) { realmURL:(NSURL *)url customFileURL:(nullable NSURL *)customFileURL isPartial:(BOOL)isPartial - stopPolicy:(RLMSyncStopPolicy)stopPolicy - errorHandler:(std::function<realm::SyncSessionErrorHandler>)errorHandler; + stopPolicy:(RLMSyncStopPolicy)stopPolicy; @end @implementation RLMSyncConfiguration @@ -106,6 +105,10 @@ BOOL isValidRealmURL(NSURL *url) { _config->is_partial = (bool)isPartial; } +- (BOOL)isPartial { + return (BOOL)_config->is_partial; +} + - (NSURL *)pinnedCertificateURL { if (auto& path = _config->ssl_trust_certificate_path) { return [NSURL fileURLWithPath:RLMStringDataToNSString(*path)]; @@ -127,11 +130,6 @@ BOOL isValidRealmURL(NSURL *url) { } } - -- (BOOL)isPartial { - return (BOOL)_config->is_partial; -} - - (void)setFullSynchronization:(BOOL)fullSynchronization { _config->is_partial = !(bool)fullSynchronization; } @@ -140,7 +138,7 @@ BOOL isValidRealmURL(NSURL *url) { return !(BOOL)_config->is_partial; } -- (realm::SyncConfig)rawConfiguration { +- (realm::SyncConfig&)rawConfiguration { return *_config; } @@ -171,6 +169,14 @@ BOOL isValidRealmURL(NSURL *url) { } } +- (bool)cancelAsyncOpenOnNonFatalErrors { + return _config->cancel_waits_on_nonfatal_error; +} + +- (void)setCancelAsyncOpenOnNonFatalErrors:(bool)cancelAsyncOpenOnNonFatalErrors { + _config->cancel_waits_on_nonfatal_error = cancelAsyncOpenOnNonFatalErrors; +} + - (NSURL *)realmURL { NSString *rawStringURL = @(_config->reference_realm_url.c_str()); return [NSURL URLWithString:rawStringURL]; @@ -181,8 +187,7 @@ BOOL isValidRealmURL(NSURL *url) { realmURL:url customFileURL:nil isPartial:NO - stopPolicy:RLMSyncStopPolicyAfterChangesUploaded - errorHandler:nullptr]; + stopPolicy:RLMSyncStopPolicyAfterChangesUploaded]; } - (instancetype)initWithUser:(RLMSyncUser *)user @@ -196,62 +201,89 @@ BOOL isValidRealmURL(NSURL *url) { realmURL:url customFileURL:nil isPartial:isPartial - stopPolicy:stopPolicy - errorHandler:nullptr]; + stopPolicy:stopPolicy]; config.urlPrefix = urlPrefix; config.enableSSLValidation = enableSSLValidation; config.pinnedCertificateURL = certificatePath; return config; } +static void bindHandler(std::string const&, SyncConfig const& config, std::shared_ptr<SyncSession> session) { + const std::shared_ptr<SyncUser>& user = config.user; + NSURL *realmURL = [NSURL URLWithString:@(config.realm_url().c_str())]; + NSString *path = [realmURL path]; + REALM_ASSERT(realmURL && path); + auto handle = [[RLMSyncSessionRefreshHandle alloc] initWithRealmURL:realmURL + user:user + session:std::move(session) + completionBlock:RLMSyncManager.sharedManager.sessionCompletionNotifier]; + context_for(user).register_refresh_handle([path UTF8String], handle); +} + +static void errorHandler(std::shared_ptr<SyncSession> errored_session, SyncError error) { + NSString *recoveryPath; + RLMSyncErrorActionToken *token; + for (auto& pair : error.user_info) { + if (pair.first == realm::SyncError::c_original_file_path_key) { + token = [[RLMSyncErrorActionToken alloc] initWithOriginalPath:pair.second]; + } + else if (pair.first == realm::SyncError::c_recovery_file_path_key) { + recoveryPath = @(pair.second.c_str()); + } + } + + BOOL shouldMakeError = YES; + NSDictionary *custom = nil; + // Note that certain types of errors are 'interactive'; users have several options + // as to how to proceed after the error is reported. + auto errorClass = errorKindForSyncError(error); + switch (errorClass) { + case RLMSyncSystemErrorKindClientReset: { + custom = @{kRLMSyncPathOfRealmBackupCopyKey: recoveryPath, kRLMSyncErrorActionTokenKey: token}; + break; + } + case RLMSyncSystemErrorKindPermissionDenied: { + custom = @{kRLMSyncErrorActionTokenKey: token}; + break; + } + case RLMSyncSystemErrorKindUser: + case RLMSyncSystemErrorKindSession: + break; + case RLMSyncSystemErrorKindConnection: + case RLMSyncSystemErrorKindClient: + case RLMSyncSystemErrorKindUnknown: + // Report the error. There's nothing the user can do about it, though. + shouldMakeError = error.is_fatal; + break; + } + auto errorHandler = RLMSyncManager.sharedManager.errorHandler; + if (!shouldMakeError || !errorHandler) { + return; + } + NSError *nsError = make_sync_error(errorClass, @(error.message.c_str()), error.error_code.value(), custom); + RLMSyncSession *session = [[RLMSyncSession alloc] initWithSyncSession:errored_session]; + dispatch_async(dispatch_get_main_queue(), ^{ + errorHandler(nsError, session); + }); +}; + - (instancetype)initWithUser:(RLMSyncUser *)user realmURL:(NSURL *)url customFileURL:(nullable NSURL *)customFileURL isPartial:(BOOL)isPartial - stopPolicy:(RLMSyncStopPolicy)stopPolicy - errorHandler:(std::function<realm::SyncSessionErrorHandler>)errorHandler { + stopPolicy:(RLMSyncStopPolicy)stopPolicy { if (self = [super init]) { if (!isValidRealmURL(url)) { @throw RLMException(@"The provided URL (%@) was not a valid Realm URL.", [url absoluteString]); } - auto bindHandler = [=](auto&, - const SyncConfig& config, - const std::shared_ptr<SyncSession>& session) { - const std::shared_ptr<SyncUser>& user = config.user; - NSURL *realmURL = [NSURL URLWithString:@(config.realm_url().c_str())]; - NSString *path = [realmURL path]; - REALM_ASSERT(realmURL && path); - RLMSyncSessionRefreshHandle *handle = [[RLMSyncSessionRefreshHandle alloc] initWithRealmURL:realmURL - user:user - session:std::move(session) - completionBlock:[RLMSyncManager sharedManager].sessionCompletionNotifier]; - context_for(user).register_refresh_handle([path UTF8String], handle); - }; - if (!errorHandler) { - errorHandler = [=](std::shared_ptr<SyncSession> errored_session, - SyncError error) { - RLMSyncSession *session = [[RLMSyncSession alloc] initWithSyncSession:errored_session]; - NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:error.user_info.size()]; - for (auto& pair : error.user_info) { - userInfo[@(pair.first.c_str())] = @(pair.second.c_str()); - } - // FIXME: how should the binding respond if the `is_fatal` bool is true? - [[RLMSyncManager sharedManager] _fireErrorWithCode:error.error_code.value() - message:@(error.message.c_str()) - isFatal:error.is_fatal - session:session - userInfo:userInfo - errorClass:errorKindForSyncError(error)]; - }; - } _config = std::make_unique<SyncConfig>(SyncConfig{ [user _syncUser], [[url absoluteString] UTF8String] }); _config->stop_policy = translateStopPolicy(stopPolicy); - _config->bind_session_handler = std::move(bindHandler); - _config->error_handler = std::move(errorHandler); + _config->bind_session_handler = bindHandler; + _config->error_handler = errorHandler; _config->is_partial = isPartial; _config->client_resync_mode = realm::ClientResyncMode::Manual; @@ -282,8 +314,7 @@ BOOL isValidRealmURL(NSURL *url) { realmURL:user.defaultRealmURL customFileURL:nil isPartial:YES - stopPolicy:RLMSyncStopPolicyAfterChangesUploaded - errorHandler:nullptr]; + stopPolicy:RLMSyncStopPolicyAfterChangesUploaded]; RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init]; config.syncConfiguration = syncConfig; return config; diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration_Private.hpp b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration_Private.hpp index e80095ef4..6314e4cb7 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration_Private.hpp +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration_Private.hpp @@ -36,12 +36,11 @@ NS_ASSUME_NONNULL_BEGIN realmURL:(NSURL *)url customFileURL:(nullable NSURL *)customFileURL isPartial:(BOOL)isPartial - stopPolicy:(RLMSyncStopPolicy)stopPolicy - errorHandler:(std::function<realm::SyncSessionErrorHandler>)errorHandler; + stopPolicy:(RLMSyncStopPolicy)stopPolicy; - (instancetype)initWithRawConfig:(realm::SyncConfig)config; -- (realm::SyncConfig)rawConfiguration; +- (realm::SyncConfig&)rawConfiguration; @end diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h index b0228e50e..debb5d4a4 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h @@ -20,7 +20,9 @@ #import "RLMSyncUtil.h" -@class RLMSyncSession; +@class RLMSyncSession, RLMSyncTimeoutOptions; + +NS_ASSUME_NONNULL_BEGIN /// An enum representing different levels of sync-related logging that can be configured. typedef RLM_CLOSED_ENUM(NSUInteger, RLMSyncLogLevel) { @@ -50,7 +52,11 @@ typedef RLM_CLOSED_ENUM(NSUInteger, RLMSyncLogLevel) { RLMSyncLogLevelAll }; -NS_ASSUME_NONNULL_BEGIN +/// A log callback function which can be set on RLMSyncManager. +/// +/// The log function may be called from multiple threads simultaneously, and is +/// responsible for performing its own synchronization if any is required. +typedef void (*RLMSyncLogFunction)(RLMSyncLogLevel level, NSString *message); /// A block type representing a block which can be used to report a sync-related error to the application. If the error /// pertains to a specific session, that session will also be passed into the block. @@ -95,7 +101,8 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable) The logging threshold which newly opened synced Realms will use. Defaults to `RLMSyncLogLevelInfo`. - Logging strings are output to Apple System Logger. + By default logging strings are output to Apple System Logger. Set `logger` to + perform custom logging logic instead. @warning This property must be set before any synced Realms are opened. Setting it after opening any synced Realm will do nothing. @@ -103,6 +110,16 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable) @property (nonatomic) RLMSyncLogLevel logLevel; /** + The function which will be invoked whenever the sync client has a log message. + + If nil, log strings are output to Apple System Logger instead. + + @warning This property must be set before any synced Realms are opened. Setting + it after opening any synced Realm will do nothing. + */ +@property (nonatomic, nullable) RLMSyncLogFunction logger; + +/** The name of the HTTP header to send authorization data in when making requests to a Realm Object Server which has been configured to expect a custom authorization header. */ @@ -141,6 +158,16 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable) */ @property (nullable, nonatomic, copy) NSDictionary<NSString *, NSURL *> *pinnedCertificatePaths; +/** + Options for the assorted types of connection timeouts for sync connections. + + If nil default values for all timeouts are used instead. + + @warning This property must be set before any synced Realms are opened. Setting + it after opening any synced Realm will do nothing. + */ +@property (nullable, nonatomic, copy) RLMSyncTimeoutOptions *timeoutOptions; + /// The sole instance of the singleton. + (instancetype)sharedManager NS_REFINED_FOR_SWIFT; @@ -150,6 +177,69 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable) /// :nodoc: + (instancetype)new __attribute__((unavailable("RLMSyncManager cannot be created directly"))); -NS_ASSUME_NONNULL_END +@end +/** + Options for configuring timeouts and intervals in the sync client. + */ +@interface RLMSyncTimeoutOptions : NSObject +/// The maximum number of milliseconds to allow for a connection to +/// become fully established. This includes the time to resolve the +/// network address, the TCP connect operation, the SSL handshake, and +/// the WebSocket handshake. +/// +/// Defaults to 2 minutes. +@property (nonatomic) NSUInteger connectTimeout; + +/// The number of milliseconds to keep a connection open after all +/// sessions have been abandoned. +/// +/// After all synchronized Realms have been closed for a given server, the +/// connection is kept open until the linger time has expire to avoid the +/// overhead of reestablishing the connection when Realms are being closed and +/// reopened. +/// +/// Defaults to 30 seconds. +@property (nonatomic) NSUInteger connectionLingerTime; + +/// The number of milliseconds between each heartbeat ping message. +/// +/// The client periodically sends ping messages to the server to check if the +/// connection is still alive. Shorter periods make connection state change +/// notifications more responsive at the cost of battery life (as the antenna +/// will have to wake up more often). +/// +/// Defaults to 1 minute. +@property (nonatomic) NSUInteger pingKeepalivePeriod; + +/// How long in milliseconds to wait for a reponse to a heartbeat ping before +/// concluding that the connection has dropped. +/// +/// Shorter values will make connection state change notifications more +/// responsive as it will only change to `disconnected` after this much time has +/// elapsed, but overly short values may result in spurious disconnection +/// notifications when the server is simply taking a long time to respond. +/// +/// Defaults to 2 minutes. +@property (nonatomic) NSUInteger pongKeepaliveTimeout; + +/// The maximum amount of time, in milliseconds, since the loss of a +/// prior connection, for a new connection to be considered a "fast +/// reconnect". +/// +/// When a client first connects to the server, it defers uploading any local +/// changes until it has downloaded all changesets from the server. This +/// typically reduces the total amount of merging that has to be done, and is +/// particularly beneficial the first time that a specific client ever connects +/// to the server. +/// +/// When an existing client disconnects and then reconnects within the "fact +/// reconnect" time this is skipped and any local changes are uploaded +/// immediately without waiting for downloads, just as if the client was online +/// the whole time. +/// +/// Defaults to 1 minute. +@property (nonatomic) NSUInteger fastReconnectLimit; @end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm index f5d2c854a..cb2e1d372 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm @@ -68,6 +68,8 @@ RLMSyncLogLevel logLevelForLevel(Level logLevel) { REALM_UNREACHABLE(); // Unrecognized log level. } +#pragma mark - Loggers + struct CocoaSyncLogger : public realm::util::RootLogger { void do_log(Level, std::string message) override { NSLog(@"Sync: %@", RLMStringDataToNSString(message)); @@ -82,21 +84,53 @@ struct CocoaSyncLoggerFactory : public realm::SyncLoggerFactory { } } s_syncLoggerFactory; +struct CallbackLogger : public realm::util::RootLogger { + RLMSyncLogFunction logFn; + void do_log(Level level, std::string message) override { + @autoreleasepool { + logFn(logLevelForLevel(level), RLMStringDataToNSString(message)); + } + } +}; +struct CallbackLoggerFactory : public realm::SyncLoggerFactory { + RLMSyncLogFunction logFn; + std::unique_ptr<realm::util::Logger> make_logger(realm::util::Logger::Level level) override { + auto logger = std::make_unique<CallbackLogger>(); + logger->logFn = logFn; + logger->set_level_threshold(level); + return std::move(logger); // not a redundant move because it's a different type + } + + CallbackLoggerFactory(RLMSyncLogFunction logFn) : logFn(logFn) { } +}; + } // anonymous namespace -@interface RLMSyncManager () -- (instancetype)initWithCustomRootDirectory:(nullable NSURL *)rootDirectory NS_DESIGNATED_INITIALIZER; +#pragma mark - RLMSyncManager + +@interface RLMSyncTimeoutOptions () { + @public + realm::SyncClientTimeouts _options; +} @end -@implementation RLMSyncManager +@implementation RLMSyncManager { + std::unique_ptr<CallbackLoggerFactory> _loggerFactory; +} static RLMSyncManager *s_sharedManager = nil; +- (instancetype)initPrivate { + return self = [super init]; +} + + (instancetype)sharedManager { static std::once_flag flag; std::call_once(flag, [] { try { - s_sharedManager = [[RLMSyncManager alloc] initWithCustomRootDirectory:nil]; + [RLMSyncUser _setUpBindingContextFactory]; + s_sharedManager = [[RLMSyncManager alloc] initPrivate]; + [s_sharedManager configureWithRootDirectory:nil]; } catch (std::exception const& e) { @throw RLMException(e); @@ -105,25 +139,23 @@ static RLMSyncManager *s_sharedManager = nil; return s_sharedManager; } -- (instancetype)initWithCustomRootDirectory:(NSURL *)rootDirectory { - if (self = [super init]) { - [RLMSyncUser _setUpBindingContextFactory]; - - // Initialize the sync engine. - SyncManager::shared().set_logger_factory(s_syncLoggerFactory); - bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION") && !RLMIsRunningInPlayground(); - auto mode = should_encrypt ? SyncManager::MetadataMode::Encryption : SyncManager::MetadataMode::NoEncryption; +- (void)configureWithRootDirectory:(NSURL *)rootDirectory { + SyncClientConfig config; + bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION") && !RLMIsRunningInPlayground(); + config.logger_factory = &s_syncLoggerFactory; + config.metadata_mode = should_encrypt ? SyncManager::MetadataMode::Encryption + : SyncManager::MetadataMode::NoEncryption; + @autoreleasepool { rootDirectory = rootDirectory ?: [NSURL fileURLWithPath:RLMDefaultDirectoryForBundleIdentifier(nil)]; - @autoreleasepool { - bool isSwift = !!NSClassFromString(@"RealmSwiftObjectUtil"); - auto userAgent = [[NSMutableString alloc] initWithFormat:@"Realm%@/%@", - isSwift ? @"Swift" : @"ObjectiveC", REALM_COCOA_VERSION]; - SyncManager::shared().configure(rootDirectory.path.UTF8String, mode, RLMStringDataWithNSString(userAgent), none, true); - SyncManager::shared().set_user_agent(RLMStringDataWithNSString(self.appID)); - } - return self; + config.base_file_path = rootDirectory.path.UTF8String; + + bool isSwift = !!NSClassFromString(@"RealmSwiftObjectUtil"); + config.user_agent_binding_info = + util::format("Realm%1/%2", isSwift ? "Swift" : "ObjectiveC", + RLMStringDataWithNSString(REALM_COCOA_VERSION)); + config.user_agent_application_info = RLMStringDataWithNSString(self.appID); } - return nil; + SyncManager::shared().configure(config); } - (NSString *)appID { @@ -153,6 +185,23 @@ static RLMSyncManager *s_sharedManager = nil; } } +- (void)setLogger:(RLMSyncLogFunction)logFn { + _logger = logFn; + if (_logger) { + _loggerFactory = std::make_unique<CallbackLoggerFactory>(logFn); + SyncManager::shared().set_logger_factory(*_loggerFactory); + } + else { + _loggerFactory = nullptr; + SyncManager::shared().set_logger_factory(s_syncLoggerFactory); + } +} + +- (void)setTimeoutOptions:(RLMSyncTimeoutOptions *)timeoutOptions { + _timeoutOptions = timeoutOptions; + SyncManager::shared().set_timeouts(timeoutOptions->_options); +} + #pragma mark - Passthrough properties - (RLMSyncLogLevel)logLevel { @@ -173,53 +222,6 @@ static RLMSyncManager *s_sharedManager = nil; }); } -- (void)_fireErrorWithCode:(int)errorCode - message:(NSString *)message - isFatal:(BOOL)fatal - session:(RLMSyncSession *)session - userInfo:(NSDictionary *)userInfo - errorClass:(RLMSyncSystemErrorKind)errorClass { - NSError *error = nil; - BOOL shouldMakeError = YES; - NSDictionary *custom = nil; - // Note that certain types of errors are 'interactive'; users have several options - // as to how to proceed after the error is reported. - switch (errorClass) { - case RLMSyncSystemErrorKindClientReset: { - std::string path = [userInfo[@(realm::SyncError::c_original_file_path_key)] UTF8String]; - custom = @{kRLMSyncPathOfRealmBackupCopyKey: - userInfo[@(realm::SyncError::c_recovery_file_path_key)], - kRLMSyncErrorActionTokenKey: - [[RLMSyncErrorActionToken alloc] initWithOriginalPath:std::move(path)] - };; - break; - } - case RLMSyncSystemErrorKindPermissionDenied: { - std::string path = [userInfo[@(realm::SyncError::c_original_file_path_key)] UTF8String]; - custom = @{kRLMSyncErrorActionTokenKey: - [[RLMSyncErrorActionToken alloc] initWithOriginalPath:std::move(path)] - }; - break; - } - case RLMSyncSystemErrorKindUser: - case RLMSyncSystemErrorKindSession: - break; - case RLMSyncSystemErrorKindConnection: - case RLMSyncSystemErrorKindClient: - case RLMSyncSystemErrorKindUnknown: - // Report the error. There's nothing the user can do about it, though. - shouldMakeError = fatal; - break; - } - error = shouldMakeError ? make_sync_error(errorClass, message, errorCode, custom) : nil; - dispatch_async(dispatch_get_main_queue(), ^{ - if (!self.errorHandler || !error) { - return; - } - self.errorHandler(error, session); - }); -} - - (NSArray<RLMSyncUser *> *)_allUsers { NSMutableArray<RLMSyncUser *> *buffer = [NSMutableArray array]; for (auto user : SyncManager::shared().all_logged_in_users()) { @@ -229,6 +231,16 @@ static RLMSyncManager *s_sharedManager = nil; } + (void)resetForTesting { + RLMSyncManager *manager = self.sharedManager; + manager->_errorHandler = nil; + manager->_appID = nil; + manager->_userAgent = nil; + manager->_logger = nil; + manager->_authorizationHeaderName = nil; + manager->_customRequestHeaders = nil; + manager->_pinnedCertificatePaths = nil; + manager->_timeoutOptions = nil; + SyncManager::shared().reset_for_testing(); } @@ -241,3 +253,43 @@ static RLMSyncManager *s_sharedManager = nil; } @end + +#pragma mark - RLMSyncTimeoutOptions + +@implementation RLMSyncTimeoutOptions +- (NSUInteger)connectTimeout { + return _options.connect_timeout; +} +- (void)setConnectTimeout:(NSUInteger)connectTimeout { + _options.connect_timeout = connectTimeout; +} + +- (NSUInteger)connectLingerTime { + return _options.connection_linger_time; +} +- (void)setConnectionLingerTime:(NSUInteger)connectionLingerTime { + _options.connection_linger_time = connectionLingerTime; +} + +- (NSUInteger)pingKeepalivePeriod { + return _options.ping_keepalive_period; +} +- (void)setPingKeepalivePeriod:(NSUInteger)pingKeepalivePeriod { + _options.ping_keepalive_period = pingKeepalivePeriod; +} + +- (NSUInteger)pongKeepaliveTimeout { + return _options.pong_keepalive_timeout; +} +- (void)setPongKeepaliveTimeout:(NSUInteger)pongKeepaliveTimeout { + _options.pong_keepalive_timeout = pongKeepaliveTimeout; +} + +- (NSUInteger)fastReconnectLimit { + return _options.fast_reconnect_limit; +} +- (void)setFastReconnectLimit:(NSUInteger)fastReconnectLimit { + _options.fast_reconnect_limit = fastReconnectLimit; +} + +@end diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager_Private.h b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager_Private.h index 7cb660b06..0284aee4f 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager_Private.h +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager_Private.h @@ -34,13 +34,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)_fireError:(NSError *)error; -- (void)_fireErrorWithCode:(int)errorCode - message:(NSString *)message - isFatal:(BOOL)fatal - session:(RLMSyncSession *)session - userInfo:(NSDictionary *)userInfo - errorClass:(RLMSyncSystemErrorKind)errorClass; - - (NSArray<RLMSyncUser *> *)_allUsers; + (void)resetForTesting; diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSessionRefreshHandle.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSessionRefreshHandle.mm index 416b7e1b5..b2de98d3b 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSessionRefreshHandle.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSessionRefreshHandle.mm @@ -58,7 +58,7 @@ static const NSTimeInterval RLMRefreshBuffer = 10; std::shared_ptr<SyncSession> _strongSession; } -@property (nonatomic) NSTimer *timer; +@property (nonatomic) dispatch_source_t timer; @property (nonatomic) NSURL *realmURL; @property (nonatomic) NSURL *authServerURL; @@ -86,19 +86,26 @@ static const NSTimeInterval RLMRefreshBuffer = 10; _session = _strongSession; _user = user; // Immediately fire off the network request. - [self _timerFired:nil]; + [self _timerFired]; return self; } return nil; } - (void)dealloc { - [self.timer invalidate]; + [self cancelTimer]; } - (void)invalidate { _strongSession = nullptr; - [self.timer invalidate]; + [self cancelTimer]; +} + +- (void)cancelTimer { + if (self.timer) { + dispatch_source_cancel(self.timer); + self.timer = nil; + } } + (NSDate *)fireDateForTokenExpirationDate:(NSDate *)date nowDate:(NSDate *)nowDate { @@ -108,43 +115,30 @@ static const NSTimeInterval RLMRefreshBuffer = 10; } - (void)scheduleRefreshTimer:(NSDate *)dateWhenTokenExpires { - // Schedule the timer on the main queue. - // It's very likely that this method will be run on a side thread, for example - // on the thread that runs `NSURLSession`'s completion blocks. We can't be - // guaranteed that there's an existing runloop on those threads, and we don't want - // to create and start a new one if one doesn't already exist. - dispatch_async(dispatch_get_main_queue(), ^{ - [self.timer invalidate]; - NSDate *fireDate = [RLMSyncSessionRefreshHandle fireDateForTokenExpirationDate:dateWhenTokenExpires - nowDate:[NSDate date]]; - if (!fireDate) { - unregisterRefreshHandle(_user, _path); - return; - } - self.timer = [[NSTimer alloc] initWithFireDate:fireDate - interval:0 - target:self - selector:@selector(_timerFired:) - userInfo:nil - repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode]; - }); -} + [self cancelTimer]; -/// Handler for network requests whose responses successfully parse into an auth response model. -- (BOOL)_handleSuccessfulRequest:(RLMAuthResponseModel *)model { - std::shared_ptr<SyncSession> session = _session.lock(); - if (!session) { - // The session is dead or in a fatal error state. + NSDate *fireDate = [RLMSyncSessionRefreshHandle fireDateForTokenExpirationDate:dateWhenTokenExpires + nowDate:[NSDate date]]; + if (!fireDate) { unregisterRefreshHandle(_user, _path); - [self invalidate]; - return NO; + return; } + NSTimeInterval timeToExpiration = [fireDate timeIntervalSinceNow]; + self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); + dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, timeToExpiration * NSEC_PER_SEC), + /* interval */ DISPATCH_TIME_FOREVER, + /* leeway */ NSEC_PER_SEC * (timeToExpiration / 10)); + dispatch_source_set_event_handler(self.timer, ^{ [self _timerFired]; }); + dispatch_resume(self.timer); +} + +/// Handler for network requests whose responses successfully parse into an auth response model. +- (BOOL)_handleSuccessfulRequest:(RLMAuthResponseModel *)model session:(SyncSession&)session { // Realm Cloud will give us a url prefix in the auth response that we need // to pass onto objectstore to have it connect to the proper sync worker if (model.urlPrefix) { - session->set_url_prefix(model.urlPrefix.UTF8String); + session.set_url_prefix(model.urlPrefix.UTF8String); } // Calculate the resolved path. @@ -159,7 +153,7 @@ static const NSTimeInterval RLMRefreshBuffer = 10; @throw RLMException(@"Resolved path returned from the server was invalid (%@).", resolvedPath); } // Pass the token and resolved path to the underlying sync subsystem. - session->refresh_access_token([model.accessToken.token UTF8String], {resolvedURLString.UTF8String}); + session.refresh_access_token([model.accessToken.token UTF8String], {resolvedURLString.UTF8String}); // Schedule a refresh. If we're successful we must already have `bind()`ed the session // initially, so we can null out the strong pointer. @@ -225,16 +219,23 @@ static const NSTimeInterval RLMRefreshBuffer = 10; /// Callback handler for network requests. - (BOOL)_onRefreshCompletionWithError:(NSError *)error json:(NSDictionary *)json { + std::shared_ptr<SyncSession> session = _session.lock(); + if (!session) { + // The session is dead or in a fatal error state. + unregisterRefreshHandle(_user, _path); + [self invalidate]; + return NO; + } + if (json && !error) { RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json requireAccessToken:YES requireRefreshToken:NO]; if (model) { - return [self _handleSuccessfulRequest:model]; + return [self _handleSuccessfulRequest:model session:*session]; } // Otherwise, malformed JSON unregisterRefreshHandle(_user, _path); - [self.timer invalidate]; NSError *error = make_sync_error(make_auth_error_bad_response(json)); if (self.completionBlock) { self.completionBlock(error); @@ -247,14 +248,13 @@ static const NSTimeInterval RLMRefreshBuffer = 10; return NO; } -- (void)_timerFired:(__unused NSTimer *)timer { +- (void)_timerFired { RLMServerToken refreshToken = nil; if (auto user = _user.lock()) { refreshToken = @(user->refresh_token().c_str()); } if (!refreshToken) { unregisterRefreshHandle(_user, _path); - [self.timer invalidate]; return; } diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncUser.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncUser.mm index 6740b8d5e..1c60cd2fa 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncUser.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncUser.mm @@ -131,7 +131,7 @@ void CocoaSyncUserContext::set_error_handler(RLMUserErrorReportingBlock block) onCompletion:(RLMUserCompletionBlock)completion { [self logInWithCredentials:credential authServerURL:authServerURL - timeout:30 + timeout:0 // use timeout from RLMSyncManager callbackQueue:dispatch_get_main_queue() onCompletion:completion]; } @@ -231,8 +231,7 @@ void CocoaSyncUserContext::set_error_handler(RLMUserErrorReportingBlock block) realmURL:url ?: self.defaultRealmURL customFileURL:nil isPartial:!fullSynchronization - stopPolicy:RLMSyncStopPolicyAfterChangesUploaded - errorHandler:nullptr]; + stopPolicy:RLMSyncStopPolicyAfterChangesUploaded]; syncConfig.urlPrefix = urlPrefix; syncConfig.enableSSLValidation = enableSSLValidation; syncConfig.pinnedCertificateURL = RLMSyncManager.sharedManager.pinnedCertificatePaths[syncConfig.realmURL.host]; diff --git a/Carthage/Checkouts/realm-cocoa/Realm/RLMUtil.mm b/Carthage/Checkouts/realm-cocoa/Realm/RLMUtil.mm index bde372eb6..59b9829c2 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/RLMUtil.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/RLMUtil.mm @@ -29,6 +29,10 @@ #import "shared_realm.hpp" +#if REALM_ENABLE_SYNC +#import "RLMSyncUtil.h" +#endif + #import <realm/mixed.hpp> #import <realm/table_view.hpp> @@ -328,12 +332,23 @@ NSError *RLMMakeError(RLMError code, const realm::RealmFileException& exception) } NSError *RLMMakeError(std::system_error const& exception) { + int code = exception.code().value(); BOOL isGenericCategoryError = (exception.code().category() == std::generic_category()); NSString *category = @(exception.code().category().name()); NSString *errorDomain = isGenericCategoryError ? NSPOSIXErrorDomain : RLMUnknownSystemErrorDomain; +#if REALM_ENABLE_SYNC + if (exception.code().category() == realm::sync::client_error_category()) { + if (exception.code().value() == static_cast<int>(realm::sync::Client::Error::connect_timeout)) { + errorDomain = NSPOSIXErrorDomain; + code = ETIMEDOUT; + } + else { + errorDomain = RLMSyncErrorDomain; + } + } +#endif - return [NSError errorWithDomain:errorDomain - code:exception.code().value() + return [NSError errorWithDomain:errorDomain code:code userInfo:@{NSLocalizedDescriptionKey: @(exception.what()), @"Error Code": @(exception.code().value()), @"Category": category}]; @@ -403,7 +418,7 @@ NSString *RLMDefaultDirectoryForBundleIdentifier(NSString *bundleIdentifier) { (void)bundleIdentifier; // tvOS prohibits writing to the Documents directory, so we use the Library/Caches directory instead. return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; -#elif TARGET_OS_IPHONE +#elif TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST (void)bundleIdentifier; // On iOS the Documents directory isn't user-visible, so put files there return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; diff --git a/Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist b/Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist index 239a10c1f..3e3045b88 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist +++ b/Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist @@ -17,11 +17,11 @@ <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleShortVersionString</key> - <string>4.1.1</string> + <string>4.3.1</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> - <string>4.1.1</string> + <string>4.3.1</string> <key>NSHumanReadableCopyright</key> <string>Copyright © 2014 Realm. All rights reserved.</string> <key>NSPrincipalClass</key> diff --git a/Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m b/Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m index f5392de87..85d84e25a 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m +++ b/Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m @@ -20,6 +20,8 @@ #import "RLMConstants.h" +#if !TARGET_OS_MACCATALYST + @interface InterprocessTest : RLMMultiProcessTestCase @end @@ -412,3 +414,5 @@ } @end + +#endif diff --git a/Carthage/Checkouts/realm-cocoa/Realm/Tests/RealmTests.mm b/Carthage/Checkouts/realm-cocoa/Realm/Tests/RealmTests.mm index 6b6a4d556..3223528ca 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/Tests/RealmTests.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/Tests/RealmTests.mm @@ -1925,15 +1925,82 @@ @autoreleasepool { [RLMRealm defaultRealm]; } }]; -// NSURL *fileURL = RLMRealmConfiguration.defaultConfiguration.fileURL; -// for (NSString *pathExtension in @[@"management", @"lock", @"note"]) { -// NSNumber *attribute = nil; -// NSError *error = nil; -// BOOL success = [[fileURL URLByAppendingPathExtension:pathExtension] getResourceValue:&attribute forKey:NSURLIsExcludedFromBackupKey error:&error]; -// XCTAssertTrue(success); -// XCTAssertNil(error); -// XCTAssertTrue(attribute.boolValue); -// } + NSURL *fileURL = RLMRealmConfiguration.defaultConfiguration.fileURL; +#if !TARGET_OS_TV + for (NSString *pathExtension in @[@"management", @"lock", @"note"]) { +#else + for (NSString *pathExtension in @[@"management", @"lock"]) { +#endif + NSNumber *attribute = nil; + NSError *error = nil; + BOOL success = [[fileURL URLByAppendingPathExtension:pathExtension] getResourceValue:&attribute forKey:NSURLIsExcludedFromBackupKey error:&error]; + XCTAssertTrue(success); + XCTAssertNil(error); + XCTAssertTrue(attribute.boolValue); + } +} + +- (void)testRealmExists { + RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; + XCTAssertFalse([RLMRealm fileExistsForConfiguration:config]); + @autoreleasepool { [RLMRealm realmWithConfiguration:config error:nil]; } + XCTAssertTrue([RLMRealm fileExistsForConfiguration:config]); + [RLMRealm deleteFilesForConfiguration:config error:nil]; + XCTAssertFalse([RLMRealm fileExistsForConfiguration:config]); +} + +- (void)testDeleteNonexistentRealmFile { + NSError *error; + XCTAssertFalse([RLMRealm deleteFilesForConfiguration:RLMRealmConfiguration.defaultConfiguration error:&error]); + XCTAssertNil(error); +} + +- (void)testDeleteClosedRealmFile { + RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; + @autoreleasepool { [RLMRealm realmWithConfiguration:config error:nil]; } + + NSError *error; + XCTAssertTrue([RLMRealm deleteFilesForConfiguration:config error:&error]); + XCTAssertNil(error); + + NSFileManager *fm = NSFileManager.defaultManager; + XCTAssertTrue([fm fileExistsAtPath:[config.fileURL.path stringByAppendingPathExtension:@"lock"]]); + XCTAssertFalse([fm fileExistsAtPath:[config.fileURL.path stringByAppendingPathExtension:@"management"]]); +#if !TARGET_OS_TV + XCTAssertFalse([fm fileExistsAtPath:[config.fileURL.path stringByAppendingPathExtension:@"note"]]); +#endif +} + +- (void)testDeleteRealmFileWithMissingManagementFiles { + RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; + [NSFileManager.defaultManager createFileAtPath:config.fileURL.path contents:nil attributes:nil]; + + NSError *error; + XCTAssertTrue([RLMRealm deleteFilesForConfiguration:config error:&error]); + XCTAssertNil(error); +} + +- (void)testDeleteRealmFileWithReadOnlyManagementFiles { + RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; + NSFileManager *fm = NSFileManager.defaultManager; + [fm createFileAtPath:config.fileURL.path contents:nil attributes:nil]; + NSString *notificationPipe = [config.fileURL.path stringByAppendingPathExtension:@"note"]; + [fm createFileAtPath:notificationPipe contents:nil attributes:@{NSFileImmutable: @YES}]; + + NSError *error; + XCTAssertTrue([RLMRealm deleteFilesForConfiguration:config error:&error]); + XCTAssertEqual(error.code, NSFileWriteNoPermissionError); + [fm setAttributes:@{NSFileImmutable: @NO} ofItemAtPath:notificationPipe error:nil]; +} + +- (void)testDeleteOpenRealmFile { + RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; + __attribute__((objc_precise_lifetime)) RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil]; + + NSError *error; + XCTAssertFalse([RLMRealm deleteFilesForConfiguration:config error:&error]); + XCTAssertEqual(error.code, RLMErrorAlreadyOpen); + XCTAssertTrue([NSFileManager.defaultManager fileExistsAtPath:config.fileURL.path]); } @end diff --git a/Carthage/Checkouts/realm-cocoa/Realm/Tests/SchemaTests.mm b/Carthage/Checkouts/realm-cocoa/Realm/Tests/SchemaTests.mm index 361d428a2..8bee02b47 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/Tests/SchemaTests.mm +++ b/Carthage/Checkouts/realm-cocoa/Realm/Tests/SchemaTests.mm @@ -742,7 +742,7 @@ RLM_ARRAY_TYPE(NotARealClass) } // Can't spawn child processes on iOS -#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR && !TARGET_OS_MACCATALYST - (void)testPartialSharedSchemaInit { if (self.isParent) { RLMRunChildAndWait(); diff --git a/Carthage/Checkouts/realm-cocoa/Realm/Tests/Swift/SwiftSchemaTests.swift b/Carthage/Checkouts/realm-cocoa/Realm/Tests/Swift/SwiftSchemaTests.swift index 54588cb53..9fb3128f6 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/Tests/Swift/SwiftSchemaTests.swift +++ b/Carthage/Checkouts/realm-cocoa/Realm/Tests/Swift/SwiftSchemaTests.swift @@ -21,6 +21,8 @@ import Realm import Realm.Private import RealmTestSupport +#if os(macOS) + class InitLinkedToClass: RLMObject { @objc dynamic var value: SwiftRLMIntObject! = SwiftRLMIntObject(value: [0]) } @@ -212,3 +214,5 @@ class SwiftRLMSchemaTests: RLMMultiProcessTestCase { "RLMArray\\<invalid class\\>") } } + +#endif diff --git a/Carthage/Checkouts/realm-cocoa/Realm/Tests/TestHost/main.m b/Carthage/Checkouts/realm-cocoa/Realm/Tests/TestHost/main.m index 58fb99fe9..bba2d436f 100644 --- a/Carthage/Checkouts/realm-cocoa/Realm/Tests/TestHost/main.m +++ b/Carthage/Checkouts/realm-cocoa/Realm/Tests/TestHost/main.m @@ -14,20 +14,20 @@ int main(int argc, const char *argv[]) { } -#elif TARGET_OS_IPHONE || TARGET_OS_TV +#elif TARGET_OS_IPHONE || TARGET_OS_TV || TARGET_OS_MACCATALYST #import <UIKit/UIKit.h> -@interface AppDelegate : UIResponder <UIApplicationDelegate> +@interface RLMAppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @end -@implementation AppDelegate +@implementation RLMAppDelegate @end int main(int argc, char *argv[]) { @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + return UIApplicationMain(argc, argv, NSStringFromClass([UIApplication class]), NSStringFromClass([RLMAppDelegate class])); } } diff --git a/Carthage/Checkouts/realm-cocoa/RealmSwift/Realm.swift b/Carthage/Checkouts/realm-cocoa/RealmSwift/Realm.swift index 9b346a7e6..4ef7ea736 100644 --- a/Carthage/Checkouts/realm-cocoa/RealmSwift/Realm.swift +++ b/Carthage/Checkouts/realm-cocoa/RealmSwift/Realm.swift @@ -764,7 +764,7 @@ public struct Realm { rlmRealm.invalidate() } - // MARK: Writing a Copy + // MARK: File Management /** Writes a compacted and optionally encrypted copy of the Realm to the given local URL. @@ -783,6 +783,43 @@ public struct Realm { try rlmRealm.writeCopy(to: fileURL, encryptionKey: encryptionKey) } + /** + Checks if the Realm file for the given configuration exists locally on disk. + + For non-synchronized, non-in-memory Realms, this is equivalent to + `FileManager.default.fileExists(atPath:)`. For synchronized Realms, it + takes care of computing the actual path on disk based on the server, + virtual path, and user as is done when opening the Realm. + + @param config A Realm configuration to check the existence of. + @return true if the Realm file for the given configuration exists on disk, false otherwise. + */ + public static func fileExists(for config: Configuration) -> Bool { + return RLMRealm.fileExists(for: config.rlmConfiguration) + } + + /** + Deletes the local Realm file and associated temporary files for the given configuration. + + This deletes the ".realm", ".note" and ".management" files which would be + created by opening the Realm with the given configuration. It does not + delete the ".lock" file (which contains no persisted data and is recreated + from scratch every time the Realm file is opened). + + The Realm must not be currently open on any thread or in another process. + If it is, this will throw the error .alreadyOpen. Attempting to open the + Realm on another thread while the deletion is happening will block, and + then create a new Realm and open that afterwards. + + If the Realm already does not exist this will return `false`. + + @param config A Realm configuration identifying the Realm to be deleted. + @return true if any files were deleted, false otherwise. + */ + public static func deleteFiles(for config: Configuration) throws -> Bool { + return try RLMRealm.deleteFiles(for: config.rlmConfiguration) + } + // MARK: Internal internal var rlmRealm: RLMRealm diff --git a/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/ObjectTests.swift b/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/ObjectTests.swift index 5320c830a..60f9b3b84 100644 --- a/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/ObjectTests.swift +++ b/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/ObjectTests.swift @@ -248,7 +248,7 @@ class ObjectTests: TestCase { let expected = object.value(forKey: "binaryCol") as! Data let actual = "a".data(using: String.Encoding.utf8)! - XCTAssertTrue(expected == actual) + XCTAssertEqual(expected, actual) XCTAssertEqual(object.value(forKey: "dateCol") as! Date?, Date(timeIntervalSince1970: 1)) XCTAssertEqual((object.value(forKey: "objectCol")! as! SwiftBoolObject).boolCol, false) @@ -256,9 +256,95 @@ class ObjectTests: TestCase { } test(SwiftObject()) - try! Realm().write { - let persistedObject = try! Realm().create(SwiftObject.self, value: [:]) - test(persistedObject) + let realm = try! Realm() + try! realm.write { + test(realm.create(SwiftObject.self, value: [:])) + let addedObj = SwiftObject() + realm.add(addedObj) + test(addedObj) + } + } + + func testValueForKeyOptionals() { + let test: (SwiftOptionalObject) -> Void = { object in + XCTAssertNil(object.value(forKey: "optNSStringCol")) + XCTAssertNil(object.value(forKey: "optStringCol")) + XCTAssertNil(object.value(forKey: "optBinaryCol")) + XCTAssertNil(object.value(forKey: "optDateCol")) + XCTAssertNil(object.value(forKey: "optIntCol")) + XCTAssertNil(object.value(forKey: "optInt8Col")) + XCTAssertNil(object.value(forKey: "optInt16Col")) + XCTAssertNil(object.value(forKey: "optInt32Col")) + XCTAssertNil(object.value(forKey: "optInt64Col")) + XCTAssertNil(object.value(forKey: "optFloatCol")) + XCTAssertNil(object.value(forKey: "optDoubleCol")) + XCTAssertNil(object.value(forKey: "optBoolCol")) + XCTAssertNil(object.value(forKey: "optEnumCol")) + } + + test(SwiftOptionalObject()) + let realm = try! Realm() + try! realm.write { + test(realm.create(SwiftOptionalObject.self, value: [:])) + let addedObj = SwiftOptionalObject() + realm.add(addedObj) + test(addedObj) + } + } + + func testValueForKeyList() { + let test: (SwiftListObject) -> Void = { object in + XCTAssertNil((object.value(forKey: "int") as! List<Int>).first) + XCTAssertNil((object.value(forKey: "int8") as! List<Int8>).first) + XCTAssertNil((object.value(forKey: "int16") as! List<Int16>).first) + XCTAssertNil((object.value(forKey: "int32") as! List<Int32>).first) + XCTAssertNil((object.value(forKey: "int64") as! List<Int64>).first) + XCTAssertNil((object.value(forKey: "float") as! List<Float>).first) + XCTAssertNil((object.value(forKey: "double") as! List<Double>).first) + XCTAssertNil((object.value(forKey: "string") as! List<String>).first) + XCTAssertNil((object.value(forKey: "data") as! List<Data>).first) + XCTAssertNil((object.value(forKey: "date") as! List<Date>).first) + + // The `as Any?` casts below are only to silence the warning about it + // happening implicitly and are not functionally required + XCTAssertNil((object.value(forKey: "intOpt") as! List<Int?>).first as Any?) + XCTAssertNil((object.value(forKey: "int8Opt") as! List<Int8?>).first as Any?) + XCTAssertNil((object.value(forKey: "int16Opt") as! List<Int16?>).first as Any?) + XCTAssertNil((object.value(forKey: "int32Opt") as! List<Int32?>).first as Any?) + XCTAssertNil((object.value(forKey: "int64Opt") as! List<Int64?>).first as Any?) + XCTAssertNil((object.value(forKey: "floatOpt") as! List<Float?>).first as Any?) + XCTAssertNil((object.value(forKey: "doubleOpt") as! List<Double?>).first as Any?) + XCTAssertNil((object.value(forKey: "stringOpt") as! List<String?>).first as Any?) + XCTAssertNil((object.value(forKey: "dataOpt") as! List<Data?>).first as Any?) + XCTAssertNil((object.value(forKey: "dateOpt") as! List<Date?>).first as Any?) + } + + test(SwiftListObject()) + let realm = try! Realm() + try! realm.write { + test(realm.create(SwiftListObject.self, value: [:])) + let addedObj = SwiftListObject() + realm.add(addedObj) + test(addedObj) + } + } + + func testValueForKeyLinkingObjects() { + let test: (SwiftDogObject) -> Void = { object in + let owners = object.value(forKey: "owners") as! LinkingObjects<SwiftOwnerObject> + if object.realm != nil { + XCTAssertEqual(owners.first!.name, "owner name") + } + } + + let dog = SwiftDogObject() + let owner = SwiftOwnerObject(value: ["owner name", dog]) + test(dog) + let realm = try! Realm() + try! realm.write { + test(realm.create(SwiftOwnerObject.self, value: owner).dog!) + realm.add(owner) + test(dog) } } diff --git a/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/PerformanceTests.swift b/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/PerformanceTests.swift index 1391a37cb..c9f07323f 100644 --- a/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/PerformanceTests.swift +++ b/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/PerformanceTests.swift @@ -48,7 +48,7 @@ class SwiftPerformanceTests: TestCase { } #else override class func defaultTestSuite() -> XCTestSuite { -#if !DEBUG && os(iOS) +#if !DEBUG && os(iOS) && !TARGET_OS_MACCATALYST if isRunningOnDevice { return super.defaultTestSuite() } diff --git a/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/RealmTests.swift b/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/RealmTests.swift index 197afc8f1..79e7675e3 100644 --- a/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/RealmTests.swift +++ b/Carthage/Checkouts/realm-cocoa/RealmSwift/Tests/RealmTests.swift @@ -845,4 +845,13 @@ class RealmTests: TestCase { XCTFail("Failed to brigde RLMError to Realm.Error") } } + + func testExists() { + let config = Realm.Configuration() + XCTAssertFalse(Realm.fileExists(for: config)) + autoreleasepool { _ = try! Realm(configuration: config) } + XCTAssertTrue(Realm.fileExists(for: config)) + XCTAssertTrue(try! Realm.deleteFiles(for: config)) + XCTAssertFalse(Realm.fileExists(for: config)) + } } diff --git a/Carthage/Checkouts/realm-cocoa/build.sh b/Carthage/Checkouts/realm-cocoa/build.sh index 0ca34965a..c3bb27a78 100755 --- a/Carthage/Checkouts/realm-cocoa/build.sh +++ b/Carthage/Checkouts/realm-cocoa/build.sh @@ -70,6 +70,8 @@ command: test-tvos-devices: tests ObjC & Swift tvOS frameworks on all attached tvOS devices test-osx: tests macOS framework test-osx-swift: tests RealmSwift macOS framework + test-catalyst: tests Mac Catalyst framework + test-catalyst-swift: tests RealmSwift Mac Catalyst framework test-swiftpm: tests ObjC and Swift macOS frameworks via SwiftPM verify: verifies docs, osx, osx-swift, ios-static, ios-dynamic, ios-swift, ios-device in both Debug and Release configurations, swiftlint verify-osx-object-server: downloads the Realm Object Server and runs the Objective-C and Swift integration tests @@ -569,7 +571,10 @@ case "$COMMAND" in exit 1 fi - xc "-scheme Realm -configuration $CONFIGURATION REALM_CATALYST_FLAGS='-target x86_64-apple-ios13.0-macabi' REALM_PLATFORM_SUFFIX='maccatalyst'" + xc "-scheme Realm -configuration $CONFIGURATION \ + REALM_CATALYST_FLAGS='-target x86_64-apple-ios13.0-macabi' \ + REALM_PLATFORM_SUFFIX='maccatalyst' \ + IS_MACCATALYST=YES" clean_retrieve "build/DerivedData/Realm/Build/Products/$CONFIGURATION/Realm.framework" "build/catalyst" "Realm.framework" ;; @@ -585,7 +590,8 @@ case "$COMMAND" in REALM_CATALYST_FLAGS='-target x86_64-apple-ios13.0-macabi' \ REALM_PLATFORM_SUFFIX='maccatalyst' \ SWIFT_DEPLOYMENT_TARGET='13.0-macabi' \ - SWIFT_PLATFORM_TARGET_PREFIX='ios'" + SWIFT_PLATFORM_TARGET_PREFIX='ios' \ + IS_MACCATALYST=YES" destination="build/catalyst/swift-$REALM_XCODE_VERSION" clean_retrieve "build/DerivedData/Realm/Build/Products/$CONFIGURATION/RealmSwift.framework" "$destination" "RealmSwift.framework" rm -rf "$destination/Realm.framework" @@ -755,6 +761,10 @@ case "$COMMAND" in sh build.sh test-tvos-devices || failed=1 sh build.sh test-osx || failed=1 sh build.sh test-osx-swift || failed=1 + if (( $(xcode_version_major) >= 11 )); then + sh build.sh test-catalyst || failed=1 + sh build.sh test-catalyst-swift || failed=1 + fi exit $failed ;; @@ -846,6 +856,20 @@ case "$COMMAND" in exit 0 ;; + "test-catalyst") + export REALM_SDKROOT=iphoneos + xc "-scheme Realm -configuration $CONFIGURATION -destination 'platform=macOS,variant=Mac Catalyst' CODE_SIGN_IDENTITY='' build-for-testing" + xc "-scheme Realm -configuration $CONFIGURATION -destination 'platform=macOS,variant=Mac Catalyst' CODE_SIGN_IDENTITY='' test" + exit 0 + ;; + + "test-catalyst-swift") + export REALM_SDKROOT=iphoneos + xc "-scheme RealmSwift -configuration $CONFIGURATION -destination 'platform=macOS,variant=Mac Catalyst' CODE_SIGN_IDENTITY='' build-for-testing" + xc "-scheme RealmSwift -configuration $CONFIGURATION -destination 'platform=macOS,variant=Mac Catalyst' CODE_SIGN_IDENTITY='' test" + exit 0 + ;; + ###################################### # Full verification ###################################### @@ -871,6 +895,10 @@ case "$COMMAND" in sh build.sh verify-swiftlint sh build.sh verify-swiftpm sh build.sh verify-osx-object-server + if (( $(xcode_version_major) >= 11 )); then + sh build.sh verify-catalyst + sh build.sh verify-catalyst-swift + fi ;; "verify-cocoapods") @@ -1017,6 +1045,16 @@ case "$COMMAND" in exit 0 ;; + "verify-catalyst") + sh build.sh test-catalyst + exit 0 + ;; + + "verify-catalyst-swift") + sh build.sh test-catalyst-swift + exit 0 + ;; + ###################################### # Docs ###################################### @@ -1256,7 +1294,7 @@ EOM sh build.sh prelaunch-simulator fi - source $(brew --prefix nvm)/nvm.sh + source $(brew --prefix nvm)/nvm.sh --no-use export REALM_NODE_PATH="$(nvm which 8)" # Reset CoreSimulator.log @@ -1512,7 +1550,7 @@ x.y.z Release notes (yyyy-MM-dd) * File format: Generates Realms with format v9 (Reads and upgrades all previous formats) * Realm Object Server: 3.21.0 or later. * APIs are backwards compatible with all previous releases in the 4.x.y series. -* Carthage release for Swift is built with Xcode 11.2. +* Carthage release for Swift is built with Xcode 11.3. ### Internal Upgraded realm-core from ? to ? diff --git a/Carthage/Checkouts/realm-cocoa/dependencies.list b/Carthage/Checkouts/realm-cocoa/dependencies.list index dc1972fcb..087212f13 100644 --- a/Carthage/Checkouts/realm-cocoa/dependencies.list +++ b/Carthage/Checkouts/realm-cocoa/dependencies.list @@ -1,4 +1,4 @@ -VERSION=4.1.1 -REALM_CORE_VERSION=5.23.6 -REALM_SYNC_VERSION=4.8.2 +VERSION=4.3.1 +REALM_CORE_VERSION=5.23.8 +REALM_SYNC_VERSION=4.9.4 REALM_OBJECT_SERVER_VERSION=3.23.1 diff --git a/Carthage/Checkouts/realm-cocoa/scripts/generate-rlmplatform.sh b/Carthage/Checkouts/realm-cocoa/scripts/generate-rlmplatform.sh index 9949212c5..c8e01b959 100755 --- a/Carthage/Checkouts/realm-cocoa/scripts/generate-rlmplatform.sh +++ b/Carthage/Checkouts/realm-cocoa/scripts/generate-rlmplatform.sh @@ -6,11 +6,12 @@ SOURCE_FILE="${SRCROOT}/Realm/RLMPlatform.h.in" DESTINATION_FILE="${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/RLMPlatform.h" TEMPORARY_FILE="${TARGET_TEMP_DIR}/RLMPlatform.h" -if [ -n "${REALM_PLATFORM_SUFFIX}" ]; then - PLATFORM_NAME="${REALM_PLATFORM_SUFFIX}" +PLATFORM_SUFFIX="$SWIFT_PLATFORM_TARGET_PREFIX" +if [ "$IS_MACCATALYST" = "YES" ]; then + PLATFORM_SUFFIX=maccatalyst fi -unifdef -B -DREALM_BUILDING_FOR_$(echo ${PLATFORM_NAME} | tr "[:lower:]" "[:upper:]") < "${SOURCE_FILE}" | sed -e "s/''/'/" > "${TEMPORARY_FILE}" +unifdef -B -DREALM_BUILDING_FOR_$(echo ${PLATFORM_SUFFIX} | tr "[:lower:]" "[:upper:]") < "${SOURCE_FILE}" | sed -e "s/''/'/" > "${TEMPORARY_FILE}" if ! cmp -s "${TEMPORARY_FILE}" "${DESTINATION_FILE}"; then echo "Updating ${DESTINATION_FILE}" diff --git a/Carthage/Checkouts/realm-cocoa/scripts/package_examples.rb b/Carthage/Checkouts/realm-cocoa/scripts/package_examples.rb index bf8f01949..32a1ee4b7 100755 --- a/Carthage/Checkouts/realm-cocoa/scripts/package_examples.rb +++ b/Carthage/Checkouts/realm-cocoa/scripts/package_examples.rb @@ -41,7 +41,7 @@ base_examples = [ "examples/tvos/swift", ] -xcode_versions = %w(10.0 10.1 10.2.1 10.3 11.0) +xcode_versions = %w(10.0 10.1 10.3 11.1 11.2.1 11.3) # Remove reference to Realm.xcodeproj from all example workspaces. base_examples.each do |example| |