diff --git a/.github/templates/build.lib.yml b/.github/templates/build.lib.yml index 5721c6ec87..c5a4b710a1 100644 --- a/.github/templates/build.lib.yml +++ b/.github/templates/build.lib.yml @@ -43,17 +43,25 @@ deploy-cluster: AtlasPrivateKey: #@ secret_AtlasPrivateKey #@ end -#@ def cleanupBaas(dependencies = []): -#@ needs = [] +#! We need to have two input arrays because there is not a 1-to-1 correspondence between dependencies +#! and targets, for example for macOS. +#@ def cleanupBaas(dependencies = [], targets = []): +#@ needs = ["deploy-cluster"] +#@ differentiators = [] #@ for dependency in dependencies: #@ needs.append(getJobName("test", dependency)) #@ end +#@ for target in targets: +#@ differentiators.append('"' + getJobName("", target) + '"') +#@ end cleanup-cluster: uses: ./.github/workflows/cleanup-baas.yml if: always() name: Cleanup needs: #@ needs with: + differentiators: #@ '[' + ", ".join(differentiators) + ']' + clusterName: ${{ needs.deploy-cluster.outputs.clusterName }} BaseUrl: #@ realm_BaseUrl AtlasBaseUrl: #@ atlas_BaseUrl secrets: diff --git a/.github/templates/main.yml b/.github/templates/main.yml index 485eb3bdae..71e090cc35 100644 --- a/.github/templates/main.yml +++ b/.github/templates/main.yml @@ -95,4 +95,4 @@ jobs: dashboard-path: dashboard.charts nuget-package: ${{ github.workspace }}/Realm/packages/Realm.${{ needs.build-packages.outputs.package_version }}.nupkg - #@ uploadArtifacts("dashboard.charts", "dashboard.charts", 30) - _: #@ template.replace(cleanupBaas([".NET Framework", "Code Coverage", "UWP Managed", "MacOS", "iOS", "Android"])) + _: #@ template.replace(cleanupBaas(dependencies = [".NET Framework", "Code Coverage", "UWP Managed", "MacOS", "iOS", "Android"], targets=[".NET Framework", "Code Coverage", "UWP Managed", "Xamarin.macOS", "iOS", "Android", "MacCatalyst"])) diff --git a/.github/templates/pr.yml b/.github/templates/pr.yml index a871f6b95f..1b0cde52e7 100644 --- a/.github/templates/pr.yml +++ b/.github/templates/pr.yml @@ -54,7 +54,7 @@ jobs: uses: ./.github/workflows/test-weaver.yml name: Test _: #@ template.replace(runTests("Code Coverage")) - _: #@ template.replace(cleanupBaas(["Code Coverage"])) + _: #@ template.replace(cleanupBaas(dependencies = ["Code Coverage"], targets = ["Code Coverage"])) verify-namespaces: runs-on: ubuntu-latest name: Verify Namespaces diff --git a/.github/templates/test-android.yml b/.github/templates/test-android.yml index 10d93348b5..4d6e619170 100644 --- a/.github/templates/test-android.yml +++ b/.github/templates/test-android.yml @@ -11,7 +11,7 @@ jobs: name: Xamarin.Android timeout-minutes: 60 steps: - - #@ template.replace(prepareTest()) + - #@ template.replace(prepareTest("android")) - #@ template.replace(buildTests("Tests/Tests.Android", target="SignAndroidPackage", AndroidUseSharedRuntime="False", EmbedAssembliesIntoApk="True")) - #@ template.replace(configureAWSCredentials("AWS_DEVICEFARM_ACCESS_KEY_ID", "AWS_DEVICEFARM_SECRET_ACCESS_KEY", "us-west-2")) - name: Run the tests diff --git a/.github/templates/test-code-coverage.yml b/.github/templates/test-code-coverage.yml index 12214b1aa8..8c934b378c 100644 --- a/.github/templates/test-code-coverage.yml +++ b/.github/templates/test-code-coverage.yml @@ -11,7 +11,7 @@ jobs: name: Code Coverage timeout-minutes: 90 steps: - - #@ template.replace(prepareTest(fetchWrappers=True)) + - #@ template.replace(prepareTest("code-coverage", fetchWrappers=True)) - name: Setup Coverlet & Report Generator run: | dotnet tool install coverlet.console --tool-path tools diff --git a/.github/templates/test-ios.yml b/.github/templates/test-ios.yml index b06fedfeb5..06893d0466 100644 --- a/.github/templates/test-ios.yml +++ b/.github/templates/test-ios.yml @@ -11,7 +11,7 @@ jobs: name: Xamarin.iOS timeout-minutes: 90 steps: - - #@ template.replace(prepareTest()) + - #@ template.replace(prepareTest("ios")) - #@ template.replace(buildTests("Tests/Tests.iOS", Platform="iPhoneSimulator")) - name: Run the tests uses: #@ actionRuniOSSimulator diff --git a/.github/templates/test-macos.yml b/.github/templates/test-macos.yml index 2b3cda6266..a1a654ef50 100644 --- a/.github/templates/test-macos.yml +++ b/.github/templates/test-macos.yml @@ -9,9 +9,9 @@ jobs: test-xamarin: runs-on: macos-latest name: Xamarin.macOS - timeout-minutes: 45 + timeout-minutes: 60 steps: - - #@ template.replace(prepareTest()) + - #@ template.replace(prepareTest("xamarinmacos")) - #@ template.replace(buildTests("Tests/Tests.XamarinMac")) - name: Run the tests run: #@ "Tests/Tests.XamarinMac/bin/" + configuration + "/Tests.XamarinMac.app/Contents/MacOS/Tests.XamarinMac --headless --result=${{ github.workspace }}/TestResults.XamarinMac.xml --labels=All" + baasTestArgs("xamarinmacos") @@ -19,7 +19,7 @@ jobs: test-maui: runs-on: macos-12 name: Maui.MacCatalyst - timeout-minutes: 45 + timeout-minutes: 60 steps: - #@ template.replace(checkoutCode()) - #@ template.replace(fetchPackageArtifacts()) diff --git a/.github/templates/test-net-core.yml b/.github/templates/test-net-core.yml index 71d00c207c..39302f9f23 100644 --- a/.github/templates/test-net-core.yml +++ b/.github/templates/test-net-core.yml @@ -38,7 +38,7 @@ jobs: env: DOTNET_DbgEnableMiniDump: 1 DOTNET_EnableCrashReport: 1 - run: #@ "${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.xml --labels=After" + baasTestArgs("net-core-${{ matrix.runner }}-${{ matrix.runtime }}") + run: #@ "${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.xml --labels=After" - name: Archive core dump uses: actions/upload-artifact@v3 if: failure() diff --git a/.github/templates/test-net-framework.yml b/.github/templates/test-net-framework.yml index 16ae0e3bc8..21e5d5946e 100644 --- a/.github/templates/test-net-framework.yml +++ b/.github/templates/test-net-framework.yml @@ -11,7 +11,7 @@ jobs: name: .NET Framework timeout-minutes: 45 steps: - - #@ template.replace(prepareTest()) + - #@ template.replace(prepareTest("net-framework")) - #@ template.replace(buildTests("Tests/Realm.Tests", TargetFramework="net461", RealmTestsStandaloneExe="true")) - name: Run the tests run: #@ "./Tests/Realm.Tests/bin/" + configuration + "/net461/Realm.Tests.exe --result=TestResults.Windows.xml --labels=After" + baasTestArgs("net-framework") diff --git a/.github/templates/test-uwp-managed.yml b/.github/templates/test-uwp-managed.yml index 10dbbc65e6..40887279aa 100644 --- a/.github/templates/test-uwp-managed.yml +++ b/.github/templates/test-uwp-managed.yml @@ -11,7 +11,7 @@ jobs: name: UWP timeout-minutes: 45 steps: - - #@ template.replace(prepareTest()) + - #@ template.replace(prepareTest("uwp-managed")) - name: Import test certificate run: | $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}") diff --git a/.github/templates/test-woven-classes.yml b/.github/templates/test-woven-classes.yml index ab33fb2a12..3343b9587d 100644 --- a/.github/templates/test-woven-classes.yml +++ b/.github/templates/test-woven-classes.yml @@ -15,5 +15,5 @@ jobs: - #@ template.replace(fetchPackageArtifacts()) - #@ template.replace(wovenClassesBuildTests("Tests/Realm.Tests", "net7.0", "win-x64")) - name: Run the tests - run: #@ "${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.WovenClasses.xml --labels=After" + baasTestArgs("weaved-classes") + run: #@ "${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.WovenClasses.xml --labels=After" - #@ publishTestsResults("TestResults.WovenClasses.xml", "Woven classes") diff --git a/.github/templates/test.lib.yml b/.github/templates/test.lib.yml index ae5fb3ce8c..549eba9f17 100644 --- a/.github/templates/test.lib.yml +++ b/.github/templates/test.lib.yml @@ -2,7 +2,7 @@ #@ load("common.lib.yml", "actionDownloadArtifact", "msbuild", "dotnetPublish", "fetchWrapperBinaries", "checkoutCode", "fetchPackageArtifacts") #@ def baasTestArgs(differentiator): -#@ return " --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=" + differentiator +#@ return " --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-"+ differentiator +" --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=" + differentiator #@ end --- #@ def publishTestsResults(files, test_title): @@ -81,7 +81,7 @@ env: #@ return dotnetPublish(projectPath, framework, runtime, properties) #@ end --- -#@ def prepareTest(fetchWrappers = False, cleanupWorkspace = False): +#@ def prepareTest(differentiator = "", fetchWrappers = False, cleanupWorkspace = False): - #@ template.replace(checkoutCode()) #@ if cleanupWorkspace: - name: Cleanup Workspace @@ -92,7 +92,10 @@ env: #@ else: - #@ template.replace(fetchPackageArtifacts()) #@ end +#@ if (differentiator != ""): +#! The following is used in case we need to re-run the action and the main deploy cluster job is not re-run too (because successful) - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 + name: Deploy Cluster (alternative) if: ${{ inputs.realmUrl }} with: projectId: ${{ secrets.AtlasProjectId}} @@ -100,5 +103,7 @@ env: atlasUrl: ${{ inputs.atlasUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: #@ "${{ inputs.clusterName }}-" + differentiator clusterSize: M10 +#@ end #@ end \ No newline at end of file diff --git a/.github/workflows/cleanup-baas.yml b/.github/workflows/cleanup-baas.yml index 1f3074653e..2a4fbd9113 100755 --- a/.github/workflows/cleanup-baas.yml +++ b/.github/workflows/cleanup-baas.yml @@ -2,6 +2,12 @@ name: cleanup-baas "on": workflow_call: inputs: + differentiators: + required: true + type: string + clusterName: + required: true + type: string BaseUrl: required: true type: string @@ -20,8 +26,11 @@ env: DOTNET_NOLOGO: true jobs: cleanup-baas: - runs-on: ubuntu-latest name: Cleanup Cluster + runs-on: ubuntu-latest + strategy: + matrix: + differentiator: ${{ fromJson(inputs.differentiators) }} timeout-minutes: 5 steps: - name: Checkout code @@ -36,3 +45,4 @@ jobs: atlasUrl: ${{ inputs.AtlasBaseUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: ${{ inputs.clusterName }}-${{ matrix.differentiator }} diff --git a/.github/workflows/deploy-baas.yml b/.github/workflows/deploy-baas.yml index 442b07f2f1..0f772a9ba5 100755 --- a/.github/workflows/deploy-baas.yml +++ b/.github/workflows/deploy-baas.yml @@ -26,12 +26,20 @@ env: DOTNET_NOLOGO: true jobs: deploy-baas: - runs-on: ubuntu-latest name: Deploy Cluster + runs-on: ubuntu-latest + strategy: + matrix: + differentiator: ${{ fromJson(inputs.differentiators) }} outputs: - clusterName: ${{ steps.deploy-cluster.outputs.clusterName }} + clusterName: ${{ steps.generate-cluster-name.outputs.clusterName }} timeout-minutes: 20 steps: + - name: Generate cluster name + id: generate-cluster-name + run: | + name=$( echo ${{ github.run_id }}-${{ github.run_attempt }} | md5sum | cut -c1-7) + echo "clusterName=$name" >> "$GITHUB_OUTPUT" - name: Checkout code uses: actions/checkout@v3 with: @@ -45,7 +53,8 @@ jobs: atlasUrl: ${{ inputs.AtlasBaseUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} - clusterSize: M20 + clusterName: ${{ steps.generate-cluster-name.outputs.clusterName }}-${{ matrix.differentiator }} + clusterSize: M5 deploy-apps: name: Deploy Apps needs: deploy-baas @@ -64,5 +73,5 @@ jobs: with: dotnet-version: 6.0.x - name: Deploy Apps - run: dotnet run . --baasurl=${{ inputs.BaseUrl }} --baascluster=${{ needs.deploy-baas.outputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey }} --baasprivateapikey=${{ secrets.AtlasPrivateKey }} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=${{ matrix.differentiator }} + run: dotnet run . --baasurl=${{ inputs.BaseUrl }} --baascluster=${{ needs.deploy-baas.outputs.clusterName }}-${{ matrix.differentiator }} --baasapikey=${{ secrets.AtlasPublicKey }} --baasprivateapikey=${{ secrets.AtlasPrivateKey }} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=${{ matrix.differentiator }} working-directory: Tools/DeployApps \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4f35d9d063..9b4d63b7b0 100755 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -301,6 +301,7 @@ jobs: if: always() name: Cleanup needs: + - deploy-cluster - test-net-framework - test-code-coverage - test-uwp-managed @@ -308,6 +309,8 @@ jobs: - test-ios - test-android with: + differentiators: '["net-framework", "code-coverage", "uwp-managed", "xamarinmacos", "ios", "android", "maccatalyst"]' + clusterName: ${{ needs.deploy-cluster.outputs.clusterName }} BaseUrl: https://realm-qa.mongodb.com AtlasBaseUrl: https://cloud-qa.mongodb.com secrets: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 8f19cac171..6a3ccb3bdc 100755 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -166,8 +166,11 @@ jobs: if: always() name: Cleanup needs: + - deploy-cluster - test-code-coverage with: + differentiators: '["code-coverage"]' + clusterName: ${{ needs.deploy-cluster.outputs.clusterName }} BaseUrl: https://realm-qa.mongodb.com AtlasBaseUrl: https://cloud-qa.mongodb.com secrets: diff --git a/.github/workflows/test-android.yml b/.github/workflows/test-android.yml index 0fbe11f500..7522fb8381 100755 --- a/.github/workflows/test-android.yml +++ b/.github/workflows/test-android.yml @@ -58,6 +58,7 @@ jobs: name: Realm.${{ inputs.version }} path: ${{ github.workspace }}/Realm/packages/ - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 + name: Deploy Cluster (alternative) if: ${{ inputs.realmUrl }} with: projectId: ${{ secrets.AtlasProjectId}} @@ -65,6 +66,7 @@ jobs: atlasUrl: ${{ inputs.atlasUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: ${{ inputs.clusterName }}-android clusterSize: M10 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -85,7 +87,7 @@ jobs: app-id: io.realm.xamarintests project-arn: ${{ secrets.DEVICEFARM_PROJECT_ARN }} device-pool-arn: ${{ secrets.DEVICEFARM_ANDROID_POOL_ARN }} - arguments: ' --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=android' + arguments: ' --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-android --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=android' - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() diff --git a/.github/workflows/test-code-coverage.yml b/.github/workflows/test-code-coverage.yml index 3430828f20..66205ea979 100755 --- a/.github/workflows/test-code-coverage.yml +++ b/.github/workflows/test-code-coverage.yml @@ -140,6 +140,7 @@ jobs: name: wrappers-windows-uwp-ARM64 path: wrappers/build - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 + name: Deploy Cluster (alternative) if: ${{ inputs.realmUrl }} with: projectId: ${{ secrets.AtlasProjectId}} @@ -147,6 +148,7 @@ jobs: atlasUrl: ${{ inputs.atlasUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: ${{ inputs.clusterName }}-code-coverage clusterSize: M10 - name: Setup Coverlet & Report Generator run: | @@ -163,7 +165,7 @@ jobs: env: DOTNET_DbgEnableMiniDump: 1 DOTNET_EnableCrashReport: 1 - run: ./tools/coverlet ${{ steps.dotnet-publish.outputs.executable-path }} -t ${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests -a '--result=TestResults.Linux.xml --labels=After --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=code-coverage' -f lcov -o ./report.lcov --exclude '[Realm.Tests]*' --exclude '[Realm.Fody]*' --exclude '[Realm.PlatformHelpers]*' + run: ./tools/coverlet ${{ steps.dotnet-publish.outputs.executable-path }} -t ${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests -a '--result=TestResults.Linux.xml --labels=After --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-code-coverage --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=code-coverage' -f lcov -o ./report.lcov --exclude '[Realm.Tests]*' --exclude '[Realm.Fody]*' --exclude '[Realm.PlatformHelpers]*' - name: Archive core dump uses: actions/upload-artifact@v3 if: failure() diff --git a/.github/workflows/test-ios.yml b/.github/workflows/test-ios.yml index a6e0998ecb..cd3b1f0804 100755 --- a/.github/workflows/test-ios.yml +++ b/.github/workflows/test-ios.yml @@ -50,6 +50,7 @@ jobs: name: Realm.${{ inputs.version }} path: ${{ github.workspace }}/Realm/packages/ - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 + name: Deploy Cluster (alternative) if: ${{ inputs.realmUrl }} with: projectId: ${{ secrets.AtlasProjectId}} @@ -57,6 +58,7 @@ jobs: atlasUrl: ${{ inputs.atlasUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: ${{ inputs.clusterName }}-ios clusterSize: M10 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -69,7 +71,7 @@ jobs: appPath: Tests/Tests.iOS/bin/iPhoneSimulator/Release/Tests.iOS.app bundleId: io.realm.dotnettests iphoneToSimulate: iPhone-8 - arguments: --headless --result=${{ github.workspace }}/TestResults.iOS.xml --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=ios + arguments: --headless --result=${{ github.workspace }}/TestResults.iOS.xml --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-ios --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=ios - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index 193a95e255..f01c7c06eb 100755 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -28,7 +28,7 @@ jobs: test-xamarin: runs-on: macos-latest name: Xamarin.macOS - timeout-minutes: 45 + timeout-minutes: 60 steps: - name: Checkout code uses: actions/checkout@v3 @@ -50,6 +50,7 @@ jobs: name: Realm.${{ inputs.version }} path: ${{ github.workspace }}/Realm/packages/ - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 + name: Deploy Cluster (alternative) if: ${{ inputs.realmUrl }} with: projectId: ${{ secrets.AtlasProjectId}} @@ -57,6 +58,7 @@ jobs: atlasUrl: ${{ inputs.atlasUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: ${{ inputs.clusterName }}-xamarinmacos clusterSize: M10 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -64,7 +66,7 @@ jobs: - name: Build Tests/Tests.XamarinMac run: msbuild Tests/Tests.XamarinMac -p:Configuration=Release -restore -p:RestoreConfigFile=Tests/Test.NuGet.Config -p:UseRealmNupkgsWithVersion=${{ inputs.version }} - name: Run the tests - run: Tests/Tests.XamarinMac/bin/Release/Tests.XamarinMac.app/Contents/MacOS/Tests.XamarinMac --headless --result=${{ github.workspace }}/TestResults.XamarinMac.xml --labels=All --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=xamarinmacos + run: Tests/Tests.XamarinMac/bin/Release/Tests.XamarinMac.app/Contents/MacOS/Tests.XamarinMac --headless --result=${{ github.workspace }}/TestResults.XamarinMac.xml --labels=All --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-xamarinmacos --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=xamarinmacos - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() @@ -79,7 +81,7 @@ jobs: test-maui: runs-on: macos-12 name: Maui.MacCatalyst - timeout-minutes: 45 + timeout-minutes: 60 steps: - name: Checkout code uses: actions/checkout@v3 @@ -105,7 +107,7 @@ jobs: - name: Build the tests run: dotnet build Tests/Tests.Maui -c Release -f net6.0-maccatalyst -p:RestoreConfigFile=Tests/Test.NuGet.Config -p:UseRealmNupkgsWithVersion=${{ inputs.version }} - name: Run the tests - run: Tests/Tests.Maui/bin/Release/net6.0-maccatalyst/maccatalyst-x64/Tests.Maui.app/Contents/MacOS/Tests.Maui --headless --result=${{ github.workspace }}/TestResults.MacCatalyst.xml --labels=All --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=maccatalyst + run: Tests/Tests.Maui/bin/Release/net6.0-maccatalyst/maccatalyst-x64/Tests.Maui.app/Contents/MacOS/Tests.Maui --headless --result=${{ github.workspace }}/TestResults.MacCatalyst.xml --labels=All --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-maccatalyst --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=maccatalyst - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() diff --git a/.github/workflows/test-net-core.yml b/.github/workflows/test-net-core.yml index 48d79d8e4e..7af144a1b7 100755 --- a/.github/workflows/test-net-core.yml +++ b/.github/workflows/test-net-core.yml @@ -74,15 +74,6 @@ jobs: with: name: Realm.${{ inputs.version }} path: ${{ github.workspace }}/Realm/packages/ - - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 - if: ${{ inputs.realmUrl }} - with: - projectId: ${{ secrets.AtlasProjectId}} - realmUrl: ${{ inputs.realmUrl }} - atlasUrl: ${{ inputs.atlasUrl}} - apiKey: ${{ secrets.AtlasPublicKey}} - privateApiKey: ${{ secrets.AtlasPrivateKey }} - clusterSize: M10 - name: Publish Tests/Realm.Tests run: dotnet publish Tests/Realm.Tests -c Release -f ${{ matrix.framework }} -r ${{ matrix.os.runtime }} -p:RestoreConfigFile=Tests/Test.NuGet.Config -p:UseRealmNupkgsWithVersion=${{ inputs.version }} -p:RealmTestsStandaloneExe=true --no-self-contained - name: Output executable path @@ -93,7 +84,7 @@ jobs: env: DOTNET_DbgEnableMiniDump: 1 DOTNET_EnableCrashReport: 1 - run: ${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.xml --labels=After --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=net-core-${{ matrix.runner }}-${{ matrix.runtime }} + run: ${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.xml --labels=After - name: Archive core dump uses: actions/upload-artifact@v3 if: failure() diff --git a/.github/workflows/test-net-framework.yml b/.github/workflows/test-net-framework.yml index 8ffc6d49de..aed0a68395 100755 --- a/.github/workflows/test-net-framework.yml +++ b/.github/workflows/test-net-framework.yml @@ -50,6 +50,7 @@ jobs: name: Realm.${{ inputs.version }} path: ${{ github.workspace }}/Realm/packages/ - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 + name: Deploy Cluster (alternative) if: ${{ inputs.realmUrl }} with: projectId: ${{ secrets.AtlasProjectId}} @@ -57,6 +58,7 @@ jobs: atlasUrl: ${{ inputs.atlasUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: ${{ inputs.clusterName }}-net-framework clusterSize: M10 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -64,7 +66,7 @@ jobs: - name: Build Tests/Realm.Tests run: msbuild Tests/Realm.Tests -p:Configuration=Release -restore -p:RestoreConfigFile=Tests/Test.NuGet.Config -p:UseRealmNupkgsWithVersion=${{ inputs.version }} -p:TargetFramework=net461 -p:RealmTestsStandaloneExe=true - name: Run the tests - run: ./Tests/Realm.Tests/bin/Release/net461/Realm.Tests.exe --result=TestResults.Windows.xml --labels=After --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=net-framework + run: ./Tests/Realm.Tests/bin/Release/net461/Realm.Tests.exe --result=TestResults.Windows.xml --labels=After --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-net-framework --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=net-framework - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() diff --git a/.github/workflows/test-tvos.yml b/.github/workflows/test-tvos.yml index d44a402e98..da2c3f0132 100755 --- a/.github/workflows/test-tvos.yml +++ b/.github/workflows/test-tvos.yml @@ -49,15 +49,6 @@ jobs: with: name: Realm.${{ inputs.version }} path: ${{ github.workspace }}/Realm/packages/ - - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 - if: ${{ inputs.realmUrl }} - with: - projectId: ${{ secrets.AtlasProjectId}} - realmUrl: ${{ inputs.realmUrl }} - atlasUrl: ${{ inputs.atlasUrl}} - apiKey: ${{ secrets.AtlasPublicKey}} - privateApiKey: ${{ secrets.AtlasPrivateKey }} - clusterSize: M10 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 if: ${{ runner.os == 'Windows' }} @@ -69,7 +60,7 @@ jobs: appPath: Tests/Tests.XamarinTVOS/bin/iPhoneSimulator/Release/Tests.XamarinTVOS.app bundleId: io.realm.Tests-XamarinTVOS iphoneToSimulate: Apple-TV-1080p - arguments: --headless --result=${{ github.workspace }}/TestResults.tvOS.xml --labels=All --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=tvos + arguments: --headless --result=${{ github.workspace }}/TestResults.tvOS.xml --labels=All --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-tvos --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=tvos os: tvOS - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b diff --git a/.github/workflows/test-uwp-managed.yml b/.github/workflows/test-uwp-managed.yml index b9ffe0b6e0..88f515e4db 100755 --- a/.github/workflows/test-uwp-managed.yml +++ b/.github/workflows/test-uwp-managed.yml @@ -54,6 +54,7 @@ jobs: name: Realm.${{ inputs.version }} path: ${{ github.workspace }}/Realm/packages/ - uses: realm/ci-actions/mdb-realm/deploy@fa20eb972b9f018654fdb4e2c7afb52b0532f907 + name: Deploy Cluster (alternative) if: ${{ inputs.realmUrl }} with: projectId: ${{ secrets.AtlasProjectId}} @@ -61,6 +62,7 @@ jobs: atlasUrl: ${{ inputs.atlasUrl}} apiKey: ${{ secrets.AtlasPublicKey}} privateApiKey: ${{ secrets.AtlasPrivateKey }} + clusterName: ${{ inputs.clusterName }}-uwp-managed clusterSize: M10 - name: Import test certificate run: | @@ -75,7 +77,7 @@ jobs: - name: Build Tests/Tests.UWP run: msbuild Tests/Tests.UWP -p:Configuration=Release -restore -p:RestoreConfigFile=Tests/Test.NuGet.Config -p:UseRealmNupkgsWithVersion=${{ inputs.version }} -p:AppxBundle=Always -p:PackageCertificateKeyFile=${{ github.workspace }}\Tests\Tests.UWP\Tests.UWP_TemporaryKey.pfx -p:PackageCertificatePassword="${{ secrets.Pfx_Password }}" -p:UseDotNetNativeToolchain=false -p:AppxBundlePlatforms=x64 - name: Run the tests - run: ./Tests/Tests.UWP/RunTests.ps1 -ExtraAppArgs ' --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=uwp-managed' + run: ./Tests/Tests.UWP/RunTests.ps1 -ExtraAppArgs ' --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }}-uwp-managed --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=uwp-managed' shell: powershell - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b diff --git a/.github/workflows/test-woven-classes.yml b/.github/workflows/test-woven-classes.yml index b9670c41c9..3531864b5e 100644 --- a/.github/workflows/test-woven-classes.yml +++ b/.github/workflows/test-woven-classes.yml @@ -56,7 +56,7 @@ jobs: run: echo 'executable-path=./Tests/Realm.Tests/bin/Release/net7.0/win-x64' >> $GITHUB_OUTPUT shell: bash - name: Run the tests - run: ${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.WovenClasses.xml --labels=After --baasurl=${{ inputs.realmUrl }} --baascluster=${{ inputs.clusterName }} --baasapikey=${{ secrets.AtlasPublicKey}} --baasprivateapikey=${{ secrets.AtlasPrivateKey}} --baasprojectid=${{ secrets.AtlasProjectId }} --baasdifferentiator=weaved-classes + run: ${{ steps.dotnet-publish.outputs.executable-path }}/Realm.Tests --result=TestResults.WovenClasses.xml --labels=After - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() diff --git a/CHANGELOG.md b/CHANGELOG.md index 6537de2623..42565b6996 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ ### Enhancements * Added `User.Changed` event that can be used to notify subscribers that something about the user changed - typically this would be the user state or the access token. (Issue [#3429](https://github.com/realm/realm-dotnet/issues/3429)) +* Streamlined some of the error codes reported in `SessionException`. A few error codes have been combined and some have been deprecated since they are no longer reported by the server. (Issue [#3295](https://github.com/realm/realm-dotnet/issues/3295)) ### Fixed * Fixed the message of the `MissingMemberException` being thrown when attempting to access a non-existent property with the dynamic API. (PR [#3432](https://github.com/realm/realm-dotnet/pull/3432)) +* Fixed a `Cannot marshal generic Windows Runtime types with a non Windows Runtime type as a generic type argument` build error when using .NET Native. (Issue [#3434](https://github.com/realm/realm-dotnet/issues/3434), since 11.4.0) ### Compatibility * Realm Studio: 13.0.0 or later. diff --git a/Realm/Realm.Weaver/Analytics/Analytics.cs b/Realm/Realm.Weaver/Analytics/Analytics.cs index abb26eb1e7..ce0e16a954 100644 --- a/Realm/Realm.Weaver/Analytics/Analytics.cs +++ b/Realm/Realm.Weaver/Analytics/Analytics.cs @@ -470,14 +470,20 @@ private string GetJsonPayload() jsonPayload.Append('{'); - AppendKeyValues(_realmEnvMetrics); - jsonPayload.Append(','); - AppendKeyValues(_realmFeaturesToAnalyze, Metric.SdkFeatures); + jsonPayload.Append(GetJsonString(_realmEnvMetrics)); + + var featuresString = GetJsonString(_realmFeaturesToAnalyze, Metric.SdkFeatures); + if (!string.IsNullOrEmpty(featuresString)) + { + jsonPayload.Append(','); + jsonPayload.Append(featuresString); + } + jsonPayload.Append('}'); return jsonPayload.ToString(); - void AppendKeyValues(IDictionary dict, IDictionary? keyMapping = null) + string GetJsonString(IDictionary dict, IDictionary? keyMapping = null) { var mapping = dict .Select(kvp => @@ -495,7 +501,7 @@ void AppendKeyValues(IDictionary dict, IDictionary s != null); - jsonPayload.Append(string.Join(",", mapping)); + return string.Join(",", mapping); } } diff --git a/Realm/Realm/Exceptions/Sync/ClientError.cs b/Realm/Realm/Exceptions/Sync/ClientError.cs index 4697cc5710..6cf93d3133 100644 --- a/Realm/Realm/Exceptions/Sync/ClientError.cs +++ b/Realm/Realm/Exceptions/Sync/ClientError.cs @@ -26,12 +26,6 @@ internal enum ClientError AutoClientResetFailed = 132, } - internal enum SessionErrorCategory : byte - { - ClientError = 0, - SessionError = 1 - } - internal enum ServerRequestsAction { NoAction = 0, diff --git a/Realm/Realm/Exceptions/Sync/ErrorCode.cs b/Realm/Realm/Exceptions/Sync/ErrorCode.cs index fd1fc7cf0d..f78d79dfeb 100644 --- a/Realm/Realm/Exceptions/Sync/ErrorCode.cs +++ b/Realm/Realm/Exceptions/Sync/ErrorCode.cs @@ -16,125 +16,201 @@ // //////////////////////////////////////////////////////////////////////////// -namespace Realms.Sync.Exceptions +using System; +using Realms.Sync.ErrorHandling; +using static System.Net.WebRequestMethods; + +namespace Realms.Sync.Exceptions; + +/// +/// Error code enumeration, indicating the type of the session error. +/// +/// +public enum ErrorCode { /// - /// Error code enumeration, indicating the type of the session error. - /// - /// - public enum ErrorCode - { - /// - /// Unrecognized error code. It usually indicates incompatibility between the authentication server and client SDK versions. - /// - Unknown = -1, - - /// - /// Other session level error has occurred. - /// - OtherSessionError = 201, - - /// - /// Path to Realm is invalid. - /// - IllegalRealmPath = 204, - - /// - /// Permission to Realm has been denied. - /// - PermissionDenied = 206, - - /// - /// The client file identifier is invalid. - /// - BadClientFileIdentifier = 208, - - /// - /// The server version is invalid. - /// - BadServerVersion = 209, - - /// - /// The client version is invalid. - /// - BadClientVersion = 210, - - /// - /// Histories have diverged and cannot be merged. - /// - DivergingHistories = 211, - - /// - /// The changeset is invalid. - /// - BadChangeset = 212, - - /// - /// The client file is invalid. - /// - BadClientFile = 217, - - /// - /// Client file has expired likely due to history compaction on the server. - /// - ClientFileExpired = 222, - - /// - /// The user for this session doesn't match the user who originally created the file. This can happen - /// if you explicitly specify the Realm file path in the configuration and you open the Realm first with - /// user A, then with user B without changing the on-disk path. - /// - UserMismatch = 223, - - /// - /// The server has received too many sessions from this client. This is typically a transient error - /// but can also indicate that the client has too many Realms open at the same time. - /// - TooManySessions = 224, - - /// - /// The client attempted to upload an invalid schema change - either an additive schema change - /// when developer mode is off or a destructive schema change. - /// - InvalidSchemaChange = 225, - - /// - /// The client attempted to create a subscription for a query is invalid/malformed. - /// - BadQuery = 226, - - /// - /// The client attempted to create an object that already exists outside their view. - /// - ObjectAlreadyExists = 227, - - /// - /// The server permissions for this file have changed since the last time it was used. - /// - ServerPermissionsChanged = 228, - - /// - /// The client tried to synchronize before initial sync has completed. Please wait for - /// the server process to complete and try again. - /// - InitialSyncNotCompleted = 229, - - /// - /// Client attempted a write that is disallowed by permissions, or modifies an object - /// outside the current query - requires client reset. - /// - WriteNotAllowed = 230, - - /// - /// Client attempted a write that is disallowed by permissions, or modifies an - /// object outside the current query, and the server undid the modification. - /// - CompensatingWrite = 231, - - /// - /// An error sent by the server when its data structures used to track client progress - /// become corrupted. - /// - BadProgress = 233, - } + /// Unrecognized error code. It usually indicates incompatibility between the App Services server and client SDK versions. + /// + RuntimeError = 1000, + + /// + /// The partition value specified by the user is not valid - i.e. its the wrong type or is encoded incorrectly. + /// + BadPartitionValue = 1029, + + /// + /// A fundamental invariant in the communication between the client and the server was not upheld. This typically indicates + /// a bug in the synchronization layer and should be reported at https://github.com/realm/realm-core/issues. + /// + ProtocolInvariantFailed = 1038, + + /// + /// The changeset is invalid. + /// + BadChangeset = 1015, + + /// + /// The client attempted to create a subscription for a query is invalid/malformed. + /// + BadQuery = 1031, + + /// + /// A client reset has occurred. This error code will only be reported via a and only + /// in the case manual client reset handling is required - either via or when + /// ManualResetFallback is invoked on one of the automatic client reset handlers. + /// + /// + /// + ClientReset = 1032, + + /// + /// The client attempted to upload an invalid schema change - either an additive schema change + /// when developer mode is off or a destructive schema change. + /// + InvalidSchemaChange = 1036, + + /// + /// Permission to Realm has been denied. + /// + PermissionDenied = 1037, + + /// + /// The server permissions for this file have changed since the last time it was used. + /// + ServerPermissionsChanged = 1040, + + /// + /// The user for this session doesn't match the user who originally created the file. This can happen + /// if you explicitly specify the Realm file path in the configuration and you open the Realm first with + /// user A, then with user B without changing the on-disk path. + /// + UserMismatch = 1041, + + /// + /// Client attempted a write that is disallowed by permissions, or modifies an object + /// outside the current query - this will result in a . + /// + WriteNotAllowed = 1044, + + /// + /// Automatic client reset has failed. This will only be reported via + /// when an automatic client reset handler was used but it failed to perform the client reset operation - + /// typically due to a breaking schema change in the server schema or due to an exception occurring in the + /// before or after client reset callbacks. + /// + AutoClientResetFailed = 1028, + + /// + /// The wrong sync type was used to connect to the server. This means that you're using + /// to connect to an app configured for flexible sync or that you're using to connect + /// to an app configured to use partition sync. + /// + WrongSyncType = 1043, + + /// + /// Unrecognized error code. It usually indicates incompatibility between the App Services server and client SDK versions. + /// + [Obsolete("Use RuntimeError instead.")] + Unknown = RuntimeError, + + /// + /// Other session level error has occurred. + /// + /// + /// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code. + /// + [Obsolete("Use RuntimeError instead.")] + OtherSessionError = RuntimeError, + + /// + /// Path to Realm is invalid. + /// + /// + /// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code. + /// + [Obsolete("Use BadPartitionValue instead")] + IllegalRealmPath = BadPartitionValue, + + /// + /// The client file identifier is invalid. + /// + /// + [Obsolete("Use ClientReset instead")] + BadClientFileIdentifier = ClientReset, + + /// + /// The server version is invalid. + /// + /// + /// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code. + /// + [Obsolete("Use ProtocolInvariantFailed instead")] + BadServerVersion = ProtocolInvariantFailed, + + /// + /// The client version is invalid. + /// + /// + /// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code. + /// + [Obsolete("Use ProtocolInvariantFailed instead")] + BadClientVersion = ProtocolInvariantFailed, + + /// + /// Histories have diverged and cannot be merged. + /// + /// + [Obsolete("Use ClientReset instead")] + DivergingHistories = ClientReset, + + /// + /// The client file is invalid. + /// + /// + [Obsolete("Use ClientReset instead")] + BadClientFile = ClientReset, + + /// + /// Client file has expired likely due to history compaction on the server. + /// + /// + [Obsolete("Use ClientReset instead")] + ClientFileExpired = ClientReset, + + /// + /// The server has received too many sessions from this client. This is typically a transient error + /// but can also indicate that the client has too many Realms open at the same time. + /// + [Obsolete("This error code is no longer reported")] + TooManySessions = -2, + + /// + /// The client attempted to create an object that already exists outside their view. + /// + [Obsolete("This error code is no longer reported")] + ObjectAlreadyExists = -3, + + /// + /// The client tried to synchronize before initial sync has completed. Please wait for + /// the server process to complete and try again. + /// + [Obsolete("This error code is no longer reported")] + InitialSyncNotCompleted = -4, + + /// + /// Client attempted a write that is disallowed by permissions, or modifies an + /// object outside the current query, and the server undid the modification. + /// + /// + CompensatingWrite = 1033, + + /// + /// An error sent by the server when its data structures used to track client progress + /// become corrupted. + /// + /// + /// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code. + /// + [Obsolete("Use ProtocolInvariantFailed instead")] + BadProgress = ProtocolInvariantFailed, } diff --git a/Realm/Realm/Extensions/TestingExtensions.cs b/Realm/Realm/Extensions/TestingExtensions.cs index ab270a54ec..8e9917138a 100644 --- a/Realm/Realm/Extensions/TestingExtensions.cs +++ b/Realm/Realm/Extensions/TestingExtensions.cs @@ -44,7 +44,7 @@ public static void SimulateError(this Session session, ErrorCode errorCode, stri Argument.NotNull(session, nameof(session)); Argument.NotNull(message, nameof(message)); - session.ReportErrorForTesting((int)errorCode, SessionErrorCategory.SessionError, message, isFatal, ServerRequestsAction.ApplicationBug); + session.ReportErrorForTesting((int)errorCode, message, isFatal, ServerRequestsAction.ApplicationBug); } } } diff --git a/Realm/Realm/Handles/SessionHandle.cs b/Realm/Realm/Handles/SessionHandle.cs index c9e98eb7bb..6fd62005bc 100644 --- a/Realm/Realm/Handles/SessionHandle.cs +++ b/Realm/Realm/Handles/SessionHandle.cs @@ -102,7 +102,7 @@ public static extern ulong register_progress_notifier(SessionHandle session, public static extern void wait(SessionHandle session, IntPtr task_completion_source, ProgressDirection direction, out NativeException ex); [DllImport(InteropConfig.DLL_NAME, EntryPoint = "realm_syncsession_report_error_for_testing", CallingConvention = CallingConvention.Cdecl)] - public static extern void report_error_for_testing(SessionHandle session, int error_code, SessionErrorCategory error_category, [MarshalAs(UnmanagedType.LPWStr)] string message, IntPtr message_len, [MarshalAs(UnmanagedType.U1)] bool is_fatal, int action); + public static extern void report_error_for_testing(SessionHandle session, int error_code, [MarshalAs(UnmanagedType.LPWStr)] string message, IntPtr message_len, [MarshalAs(UnmanagedType.U1)] bool is_fatal, int action); [DllImport(InteropConfig.DLL_NAME, EntryPoint = "realm_syncsession_stop", CallingConvention = CallingConvention.Cdecl)] public static extern void stop(SessionHandle session, out NativeException ex); @@ -246,9 +246,9 @@ public IntPtr GetRawPointer() return NativeMethods.get_raw_pointer(this); } - public void ReportErrorForTesting(int errorCode, SessionErrorCategory errorCategory, string errorMessage, bool isFatal, ServerRequestsAction action) + public void ReportErrorForTesting(int errorCode, string errorMessage, bool isFatal, ServerRequestsAction action) { - NativeMethods.report_error_for_testing(this, errorCode, errorCategory, errorMessage, (IntPtr)errorMessage.Length, isFatal, (int)action); + NativeMethods.report_error_for_testing(this, errorCode, errorMessage, (IntPtr)errorMessage.Length, isFatal, (int)action); } public void Stop() diff --git a/Realm/Realm/Native/HttpClientTransport.cs b/Realm/Realm/Native/HttpClientTransport.cs index 91f0ee7c4a..c435dbd915 100644 --- a/Realm/Realm/Native/HttpClientTransport.cs +++ b/Realm/Realm/Native/HttpClientTransport.cs @@ -59,7 +59,7 @@ private readonly struct HttpClientRequest public readonly UInt64 timeout_ms; - public readonly MarshaledVector> headers; + public readonly MarshaledVector> headers; private readonly StringValue body; @@ -91,7 +91,7 @@ private struct HttpClientResponse public CustomErrorCode custom_status_code; - public MarshaledVector> headers; + public MarshaledVector> headers; public StringValue body; } @@ -148,13 +148,13 @@ private static async void ExecuteRequest(HttpClientRequest request, IntPtr callb var response = await httpClient.SendAsync(message, cts.Token).ConfigureAwait(false); var headers = response.Headers.Concat(response.Content.Headers) - .Select(h => new KeyValuePair(StringValue.AllocateFrom(h.Key, arena), StringValue.AllocateFrom(h.Value.FirstOrDefault(), arena))) + .Select(h => new MarshaledPair(StringValue.AllocateFrom(h.Key, arena), StringValue.AllocateFrom(h.Value.FirstOrDefault(), arena))) .ToArray(); var nativeResponse = new HttpClientResponse { http_status_code = (int)response.StatusCode, - headers = MarshaledVector>.AllocateFrom(headers, arena), + headers = MarshaledVector>.AllocateFrom(headers, arena), body = StringValue.AllocateFrom(await response.Content.ReadAsStringAsync().ConfigureAwait(false), arena), }; diff --git a/Realm/Realm/Native/MarshaledPair.cs b/Realm/Realm/Native/MarshaledPair.cs new file mode 100644 index 0000000000..babfc46b0a --- /dev/null +++ b/Realm/Realm/Native/MarshaledPair.cs @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2023 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. +// +//////////////////////////////////////////////////////////////////////////// + +using System.Collections.Generic; + +namespace Realms.Native +{ + internal struct MarshaledPair + where TKey : unmanaged + where TValue : unmanaged + { + public TKey Key; + + public TValue Value; + + public MarshaledPair(TKey key, TValue value) + { + Key = key; + Value = value; + } + + public void Deconstruct(out TKey key, out TValue value) + { + key = Key; + value = Value; + } + + public static implicit operator KeyValuePair(MarshaledPair pair) => new (pair.Key, pair.Value); + } +} diff --git a/Realm/Realm/Native/SyncError.cs b/Realm/Realm/Native/SyncError.cs index 6e45cdb794..09ecae53a5 100644 --- a/Realm/Realm/Native/SyncError.cs +++ b/Realm/Realm/Native/SyncError.cs @@ -34,7 +34,7 @@ internal struct SyncError [MarshalAs(UnmanagedType.U1)] public bool is_client_reset; - public MarshaledVector> user_info_pairs; + public MarshaledVector> user_info_pairs; public MarshaledVector compensating_writes; diff --git a/Realm/Realm/Sync/Session.cs b/Realm/Realm/Sync/Session.cs index ac20ce3437..a07eb8496d 100644 --- a/Realm/Realm/Sync/Session.cs +++ b/Realm/Realm/Sync/Session.cs @@ -222,7 +222,8 @@ internal void CloseHandle(bool waitForShutdown = false) } } - internal void ReportErrorForTesting(int errorCode, SessionErrorCategory sessionErrorCategory, string errorMessage, bool isFatal, ServerRequestsAction action) => Handle.ReportErrorForTesting(errorCode, sessionErrorCategory, errorMessage, isFatal, action); + internal void ReportErrorForTesting(int errorCode, string errorMessage, bool isFatal, ServerRequestsAction action) + => Handle.ReportErrorForTesting(errorCode, errorMessage, isFatal, action); internal void RaisePropertyChanged(string propertyName) { diff --git a/Tests/Realm.Tests/Sync/AsymmetricObjectTests.cs b/Tests/Realm.Tests/Sync/AsymmetricObjectTests.cs index 59c8c1cf89..a7fa3431d0 100644 --- a/Tests/Realm.Tests/Sync/AsymmetricObjectTests.cs +++ b/Tests/Realm.Tests/Sync/AsymmetricObjectTests.cs @@ -28,8 +28,6 @@ using Realms.Sync; #if TEST_WEAVER using TestAsymmetricObject = Realms.AsymmetricObject; -using TestEmbeddedObject = Realms.EmbeddedObject; -using TestRealmObject = Realms.RealmObject; #else using TestAsymmetricObject = Realms.IAsymmetricObject; #endif @@ -90,31 +88,12 @@ public class AsymmetricObjectTests : SyncTestBase new object[] { "NullableGuidProperty", Guid.Parse("{C4EC8CEF-D62A-405E-83BB-B0A3D8DABB36}") } }; - [Test] - public void AddAsymmetricObjNotInSchema_Throws() - { - SyncTestHelpers.RunBaasTestAsync(async () => - { - var flxConfig = await GetFLXIntegrationConfigAsync(); - using var realm = await GetRealmAsync(flxConfig); - - Assert.Throws(() => - { - realm.Write(() => - { - realm.Add(new BasicAsymmetricObject()); - }); - }); - }); - } - [Test] public void AddCollectionOfAsymmetricObjs() { SyncTestHelpers.RunBaasTestAsync(async () => { var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(BasicAsymmetricObject) }; using var realm = await GetRealmAsync(flxConfig); var partitionLike = Guid.NewGuid().ToString(); @@ -148,7 +127,6 @@ public void AddCollection_WithSomeObjectsAlreadyAdded_Throws() SyncTestHelpers.RunBaasTestAsync(async () => { var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(BasicAsymmetricObject) }; using var realm = await GetRealmAsync(flxConfig); var partitionLike = Guid.NewGuid().ToString(); @@ -183,7 +161,6 @@ public void AddHugeAsymmetricObj() ObjectId id = default; var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(AsymmetricObjectWithAllTypes) }; using var realm = await GetRealmAsync(flxConfig); realm.Write(() => @@ -206,9 +183,7 @@ public void AccessAsymmetricObjAfterAddedToRealm_Throws() SyncTestHelpers.RunBaasTestAsync(async () => { var partitionLike = Guid.NewGuid().ToString(); - var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(BasicAsymmetricObject) }; - using var realm = await GetRealmAsync(flxConfig); + using var realm = await GetFLXIntegrationRealmAsync(); var asymmetribObj = new BasicAsymmetricObject { @@ -233,9 +208,7 @@ public void AddSameAsymmetricObjTwice_Throws() { SyncTestHelpers.RunBaasTestAsync(async () => { - var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(BasicAsymmetricObject) }; - using var realm = await GetRealmAsync(flxConfig); + using var realm = await GetFLXIntegrationRealmAsync(); var partitionLike = Guid.NewGuid().ToString(); var asymmetricObj = new BasicAsymmetricObject { @@ -261,8 +234,6 @@ public void SetAndRemotelyReadValue(string propertyName, object propertyValue) { ObjectId id = default; var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(AsymmetricObjectWithAllTypes) }; - using var realm = await GetRealmAsync(flxConfig); realm.Write(() => @@ -290,7 +261,6 @@ public void MixAddingObjectAsymmetricAndNot() var partitionLike = Guid.NewGuid().ToString(); var id = new Random().Next(); var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(BasicAsymmetricObject), typeof(PrimaryKeyInt32Object) }; flxConfig.PopulateInitialSubscriptions = (realm) => { @@ -346,15 +316,7 @@ public void EmbeddedObject_WhenParentAccessed_ReturnsParent() { SyncTestHelpers.RunBaasTestAsync(async () => { - var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] - { - typeof(AsymmetricObjectWithEmbeddedRecursiveObject), - typeof(EmbeddedLevel1), - typeof(EmbeddedLevel2), - typeof(EmbeddedLevel3) - }; - using var realm = await GetRealmAsync(flxConfig); + using var realm = await GetFLXIntegrationRealmAsync(); var parent = new AsymmetricObjectWithEmbeddedRecursiveObject { @@ -387,9 +349,7 @@ public void EmbeddedObject_WhenParentAccessedInList_ReturnsParent() { SyncTestHelpers.RunBaasTestAsync(async () => { - var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(AsymmetricObjectWithEmbeddedListObject), typeof(EmbeddedIntPropertyObject) }; - using var realm = await GetRealmAsync(flxConfig); + using var realm = await GetFLXIntegrationRealmAsync(); var parent = new AsymmetricObjectWithEmbeddedListObject(); parent.EmbeddedListObject.Add(new EmbeddedIntPropertyObject()); @@ -408,9 +368,7 @@ public void EmbeddedObject_WhenParentAccessedInDictionary_ReturnsParent() { SyncTestHelpers.RunBaasTestAsync(async () => { - var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(AsymmetricObjectWithEmbeddedDictionaryObject), typeof(EmbeddedIntPropertyObject) }; - using var realm = await GetRealmAsync(flxConfig); + using var realm = await GetFLXIntegrationRealmAsync(); var parent = new AsymmetricObjectWithEmbeddedDictionaryObject(); parent.EmbeddedDictionaryObject.Add("child", new EmbeddedIntPropertyObject()); @@ -452,9 +410,7 @@ public void NonEmbeddedObject_WhenParentAccessed_Throws() { SyncTestHelpers.RunBaasTestAsync(async () => { - var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(BasicAsymmetricObject) }; - using var realm = await GetRealmAsync(flxConfig); + using var realm = await GetFLXIntegrationRealmAsync(); var topLevel = new BasicAsymmetricObject { @@ -627,7 +583,6 @@ public void DynamicAccess([Values(true, false)] bool isDynamic) { var flxConfig = await GetFLXIntegrationConfigAsync(); flxConfig.IsDynamic = isDynamic; - flxConfig.Schema = new[] { typeof(AsymmetricObjectWithAllTypes) }; using var realm = await GetRealmAsync(flxConfig); realm.Write(() => @@ -698,7 +653,6 @@ private static Task GetRemoteObjects(User user, string remoteFieldName, private async Task GetRealmWithRealmValueSchemaAsync() { var flxConfig = await GetFLXIntegrationConfigAsync(); - flxConfig.Schema = new[] { typeof(RealmValueObject), typeof(BasicAsymmetricObject) }; flxConfig.PopulateInitialSubscriptions = (realm) => { var query = realm.All(); diff --git a/Tests/Realm.Tests/Sync/FlexibleSyncTests.cs b/Tests/Realm.Tests/Sync/FlexibleSyncTests.cs index efa2fb8603..999927d4d2 100644 --- a/Tests/Realm.Tests/Sync/FlexibleSyncTests.cs +++ b/Tests/Realm.Tests/Sync/FlexibleSyncTests.cs @@ -2211,6 +2211,8 @@ public void Results_Subscribe_FirstTimeOnly_DoesntWaitForChanges([Values("abc", writerRealm.Add(new SyncAllTypesObject { DoubleProperty = 3.5, GuidProperty = testGuid, }); }); + await WaitForUploadAsync(writerRealm); + // Resubscribe to the same query with waitForSync.FirstTime. Since // we already have this subscription, SubscribeAsync should return // immediately without waiting for the download to happen. diff --git a/Tests/Realm.Tests/Sync/SessionTests.cs b/Tests/Realm.Tests/Sync/SessionTests.cs index 48fbeb0a77..a415b73427 100644 --- a/Tests/Realm.Tests/Sync/SessionTests.cs +++ b/Tests/Realm.Tests/Sync/SessionTests.cs @@ -136,7 +136,7 @@ public void Session_ClientReset_ManualRecovery_InitiateClientReset(string appTyp Assert.That(clientEx.Message, Does.Contain("Bad client file identifier")); Assert.That(clientEx.InnerException, Is.Null); - await TryInitiateClientReset(realm, clientEx, (int)ErrorCode.BadClientFileIdentifier); + await TryInitiateClientReset(realm, clientEx, ErrorCode.ClientReset); }); } @@ -169,7 +169,7 @@ void beforeCb(Realm _) var clientEx = await errorTcs.Task.Timeout(20_000, "Expected client reset"); - await TryInitiateClientReset(realm, clientEx, (int)ClientError.AutoClientResetFailed); + await TryInitiateClientReset(realm, clientEx, ErrorCode.AutoClientResetFailed); }); } @@ -216,6 +216,8 @@ public void Session_AutomaticRecoveryFallsbackToDiscardLocal(string appType) { SyncTestHelpers.RunBaasTestAsync(async () => { + await DisableClientResetRecoveryOnServer(appType); + var automaticResetCalled = false; var discardLocalResetCalled = false; @@ -254,7 +256,6 @@ public void Session_AutomaticRecoveryFallsbackToDiscardLocal(string appType) realm.Add(new ObjectWithPartitionValue(guid)); }); - await DisableClientResetRecoveryOnServer(appType); await TriggerClientReset(realm); await tcsAfterClientReset.Task.Timeout(20_000, detail: "Expected client reset"); @@ -410,8 +411,6 @@ public void SessionIntegrationTest_ClientResetHandlers_OutOfBoundArrayInsert_Add config = GetIntegrationConfig(user); } - config.Schema = new[] { typeof(ObjectWithPartitionValue) }; - return (config, guid); } @@ -731,7 +730,7 @@ public void Session_OnSessionError() { Assert.That(sender, Is.InstanceOf()); Assert.That(e, Is.InstanceOf()); - Assert.That(e.ErrorCode, Is.EqualTo(ErrorCode.TooManySessions)); + Assert.That(e.ErrorCode, Is.EqualTo(ErrorCode.WriteNotAllowed)); Assert.That(e.Message, Is.EqualTo(errorMsg)); Assert.That(e.InnerException, Is.Null); Assert.That(sessionErrorTriggered, Is.False); @@ -741,7 +740,9 @@ public void Session_OnSessionError() using var realm = await GetRealmAsync(config, waitForSync: true); var session = GetSession(realm); - session.SimulateError(ErrorCode.TooManySessions, errorMsg); + + var protocolError = 230; // ProtocolError::write_not_allowed + session.SimulateError((ErrorCode)protocolError, errorMsg); await tcs.Task; @@ -1189,7 +1190,7 @@ public void Session_WhenDisposed_MethodsThrow() Assert.Throws(() => _ = session.Equals(session)); Assert.Throws(() => _ = session.WaitForDownloadAsync()); Assert.Throws(() => _ = session.WaitForUploadAsync()); - Assert.Throws(() => session.ReportErrorForTesting(1, SessionErrorCategory.SessionError, "test", false, ServerRequestsAction.ApplicationBug)); + Assert.Throws(() => session.ReportErrorForTesting(1, "test", false, ServerRequestsAction.ApplicationBug)); // Calling CloseHandle multiple times should be fine session.CloseHandle(); @@ -1458,14 +1459,14 @@ private static ClientResetHandlerBase GetClientResetHandler( return handler; } - private static async Task TryInitiateClientReset(Realm realm, ClientResetException ex, int expectedError) + private static async Task TryInitiateClientReset(Realm realm, ClientResetException ex, ErrorCode expectedError) { if (!realm.IsClosed) { realm.Dispose(); } - Assert.That((int)ex.ErrorCode, Is.EqualTo(expectedError)); + Assert.That(ex.ErrorCode, Is.EqualTo(expectedError)); Assert.That(File.Exists(realm.Config.DatabasePath), Is.True); var didReset = false; diff --git a/Tests/Realm.Tests/Sync/SyncTestBase.cs b/Tests/Realm.Tests/Sync/SyncTestBase.cs index 39e5b94b2c..9af7590fbd 100644 --- a/Tests/Realm.Tests/Sync/SyncTestBase.cs +++ b/Tests/Realm.Tests/Sync/SyncTestBase.cs @@ -22,6 +22,7 @@ using System.Threading.Tasks; using Baas; using MongoDB.Bson; +using Realms.Schema; using Realms.Sync; using Realms.Sync.Exceptions; using static Realms.Tests.TestHelpers; @@ -220,7 +221,36 @@ protected async Task GetRealmAsync(SyncConfigurationBase config, bool wai private static T UpdateConfig(T config) where T : SyncConfigurationBase { - config.Schema = new[] { typeof(HugeSyncObject), typeof(PrimaryKeyStringObject), typeof(ObjectIdPrimaryKeyWithValueObject), typeof(SyncCollectionsObject), typeof(IntPropertyObject), typeof(EmbeddedIntPropertyObject), typeof(SyncAllTypesObject) }; + var schema = new RealmSchema.Builder() + { + typeof(HugeSyncObject), + typeof(PrimaryKeyStringObject), + typeof(ObjectIdPrimaryKeyWithValueObject), + typeof(SyncCollectionsObject), + typeof(IntPropertyObject), + typeof(EmbeddedIntPropertyObject), + typeof(SyncAllTypesObject), + typeof(ObjectWithPartitionValue), + }; + + if (config is FlexibleSyncConfiguration) + { + // We need to add all objects ever used by sync to the flx schema due to the way breaking schema changes work + // in dev mode. When a client connects with a subset of the server schema, they'll experience client reset as the + // server removes the missing tables and re-bootstraps. + schema.Add(typeof(BasicAsymmetricObject)); + schema.Add(typeof(AsymmetricObjectWithAllTypes)); + schema.Add(typeof(AsymmetricObjectWithEmbeddedRecursiveObject)); + schema.Add(typeof(EmbeddedLevel1)); + schema.Add(typeof(EmbeddedLevel2)); + schema.Add(typeof(EmbeddedLevel3)); + schema.Add(typeof(RealmValueObject)); + schema.Add(typeof(AsymmetricObjectWithEmbeddedDictionaryObject)); + schema.Add(typeof(AsymmetricObjectWithEmbeddedListObject)); + schema.Add(typeof(PrimaryKeyInt32Object)); + } + + config.Schema = schema; config.SessionStopPolicy = SessionStopPolicy.Immediately; return config; diff --git a/Tools/DeployApps/BaasClient.cs b/Tools/DeployApps/BaasClient.cs index 6729bad2ed..fa3ece4eee 100644 --- a/Tools/DeployApps/BaasClient.cs +++ b/Tools/DeployApps/BaasClient.cs @@ -135,17 +135,18 @@ public class FunctionReturn private string _groupId = null!; private string? _refreshToken; - private string _shortDifferentiator + private string _shortSuffix { get { - if (Differentiator.Length < 8) + var completeSuffix = $"{Differentiator}-{_clusterName}"; + if (completeSuffix.Length < 8) { - return Differentiator; + return completeSuffix; } using var sha = SHA256.Create(); - var inputBytes = Encoding.ASCII.GetBytes(Differentiator); + var inputBytes = Encoding.ASCII.GetBytes(completeSuffix); var hashBytes = sha.ComputeHash(inputBytes); var sb = new StringBuilder(); @@ -158,7 +159,7 @@ private string _shortDifferentiator } } - private string _appSuffix => $"-{_shortDifferentiator}-{_clusterName}"; + private string _appSuffix => $"-{_shortSuffix}"; public string Differentiator { get; } @@ -535,11 +536,6 @@ private async Task GetApps() { var name = doc["name"].AsString; - if (!name.EndsWith(_appSuffix)) - { - return null; - } - var appName = name[..^_appSuffix.Length]; return new BaasApp(doc["_id"].AsString, doc["client_app_id"].AsString, appName); }) diff --git a/wrappers/realm-core b/wrappers/realm-core index 03ba58ace5..673be45ce2 160000 --- a/wrappers/realm-core +++ b/wrappers/realm-core @@ -1 +1 @@ -Subproject commit 03ba58ace5d29685154a9287d1f914aabd9b4928 +Subproject commit 673be45ce266cef009ac5af58e8ff7327dd0d234 diff --git a/wrappers/src/error_handling.cpp b/wrappers/src/error_handling.cpp index 2438ecb37b..7ac267441d 100644 --- a/wrappers/src/error_handling.cpp +++ b/wrappers/src/error_handling.cpp @@ -62,7 +62,7 @@ namespace realm { catch (const SyncError& e) { REALM_ASSERT_DEBUG(false); - return NativeException(e); + return NativeException(e.status.code(), e.status.reason()); } catch (const Exception& e) { return NativeException(e); diff --git a/wrappers/src/shared_realm_cs.cpp b/wrappers/src/shared_realm_cs.cpp index ee687a90ed..53dc338c9e 100644 --- a/wrappers/src/shared_realm_cs.cpp +++ b/wrappers/src/shared_realm_cs.cpp @@ -178,7 +178,7 @@ Realm::Config get_shared_realm_config(Configuration configuration, std::optional config.schema_mode = sync_configuration->schema_mode; if (sync_configuration->is_flexible_sync) { - config.sync_config = std::make_shared(*sync_configuration->user, realm::SyncConfig::FLXSyncEnabled{}); + config.sync_config = std::make_shared(*sync_configuration->user, realm::SyncConfig::FLXSyncEnabled{}); } else { std::string partition(Utf16StringAccessor(sync_configuration->partition, sync_configuration->partition_len)); @@ -202,7 +202,7 @@ Realm::Config get_shared_realm_config(Configuration configuration, std::optional } realm_sync_error marshaled_error{ - error.get_system_error().value(), + error.status.code(), to_capi(error.simple_message), to_capi(error.logURL), error.is_client_reset_requested(), diff --git a/wrappers/src/sync_session_cs.cpp b/wrappers/src/sync_session_cs.cpp index 96ecd8339b..c4f915a0c5 100644 --- a/wrappers/src/sync_session_cs.cpp +++ b/wrappers/src/sync_session_cs.cpp @@ -175,24 +175,13 @@ enum class SessionErrorCategory : uint8_t { SessionError = 1 }; -REALM_EXPORT void realm_syncsession_report_error_for_testing(const SharedSyncSession& session, int err, SessionErrorCategory error_category, const uint16_t* message_buf, size_t message_len, bool is_fatal, int server_requests_action) +REALM_EXPORT void realm_syncsession_report_error_for_testing(const SharedSyncSession& session, int err, const uint16_t* message_buf, size_t message_len, bool is_fatal, int server_requests_action) { Utf16StringAccessor message(message_buf, message_len); std::error_code error_code; - switch (error_category) { - case SessionErrorCategory::ClientError: - error_code = std::error_code(err, realm::sync::client_error_category()); - break; - case SessionErrorCategory::SessionError: - error_code = std::error_code(err, realm::sync::protocol_error_category()); - break; - default: - // in case a new category isn't handle, just don't trigger any error - return; - } - - sync::SessionErrorInfo error{ error_code, std::move(message), is_fatal }; + sync::ProtocolErrorInfo protocol_error(err, message, is_fatal); + sync::SessionErrorInfo error(protocol_error); error.server_requests_action = static_cast(server_requests_action); SyncSession::OnlyForTesting::handle_error(*session, std::move(error)); diff --git a/wrappers/src/websocket_cs.cpp b/wrappers/src/websocket_cs.cpp index 419c6e34a4..635c8b399c 100644 --- a/wrappers/src/websocket_cs.cpp +++ b/wrappers/src/websocket_cs.cpp @@ -187,7 +187,7 @@ extern "C" { } REALM_EXPORT void realm_websocket_observer_closed_handler(WebSocketObserver* observer, bool was_clean, websocket::WebSocketError error_code, realm_string_t reason) { - observer->websocket_closed_handler(was_clean, Status(error_code, from_capi(reason))); + observer->websocket_closed_handler(was_clean, error_code, capi_to_std(reason)); } }