diff --git a/.github/templates/test.lib.yml b/.github/templates/test.lib.yml index e3df7d41e8..719b8b42de 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 " --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=" + differentiator +#@ return " --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=" + differentiator + "-${{ github.run_id }}-${{ github.run_attempt }}" #@ end --- #@ def publishTestsResults(files, test_title): @@ -86,7 +86,7 @@ env: env: apiKey: ${{ secrets.BaaSaasApiKey }} if: ${{ env.apiKey }} - run: #@ "dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=" + differentiator + run: #@ "dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=" + differentiator + "-${{ github.run_id }}-${{ github.run_attempt }}" working-directory: Tools/DeployApps #@ end #@ end \ No newline at end of file diff --git a/.github/workflows/cleanup-baas.yml b/.github/workflows/cleanup-baas.yml index c6b5153104..2237b54bd4 100755 --- a/.github/workflows/cleanup-baas.yml +++ b/.github/workflows/cleanup-baas.yml @@ -29,5 +29,5 @@ jobs: with: dotnet-version: 6.0.x - name: Terminate Baas - run: dotnet run terminate-baas --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=${{ matrix.differentiator }} + run: dotnet run terminate-baas --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=${{ matrix.differentiator }}-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps \ No newline at end of file diff --git a/.github/workflows/deploy-baas.yml b/.github/workflows/deploy-baas.yml index 8e81913c1a..e1ff8b7431 100755 --- a/.github/workflows/deploy-baas.yml +++ b/.github/workflows/deploy-baas.yml @@ -29,5 +29,5 @@ jobs: with: dotnet-version: 6.0.x - name: Deploy Apps - run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=${{ matrix.differentiator }} + run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=${{ matrix.differentiator }}-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps \ No newline at end of file diff --git a/.github/workflows/test-android.yml b/.github/workflows/test-android.yml index 967ceb6431..bc85c7912c 100755 --- a/.github/workflows/test-android.yml +++ b/.github/workflows/test-android.yml @@ -53,7 +53,7 @@ jobs: env: apiKey: ${{ secrets.BaaSaasApiKey }} if: ${{ env.apiKey }} - run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=android + run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=android-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -74,7 +74,7 @@ jobs: app-id: io.realm.xamarintests project-arn: ${{ secrets.DEVICEFARM_PROJECT_ARN }} device-pool-arn: ${{ secrets.DEVICEFARM_ANDROID_POOL_ARN }} - arguments: ' --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=android' + arguments: ' --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=android-${{ github.run_id }}-${{ github.run_attempt }}' - 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 f5b4105f18..762397a5cc 100755 --- a/.github/workflows/test-code-coverage.yml +++ b/.github/workflows/test-code-coverage.yml @@ -130,7 +130,7 @@ jobs: env: apiKey: ${{ secrets.BaaSaasApiKey }} if: ${{ env.apiKey }} - run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=code-coverage + run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=code-coverage-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps - name: Setup Coverlet & Report Generator run: | @@ -147,7 +147,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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=code-coverage-${{ github.run_id }}-${{ github.run_attempt }}' -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 340c947dc8..8d621c221b 100755 --- a/.github/workflows/test-ios.yml +++ b/.github/workflows/test-ios.yml @@ -40,7 +40,7 @@ jobs: env: apiKey: ${{ secrets.BaaSaasApiKey }} if: ${{ env.apiKey }} - run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=ios + run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=ios-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -53,7 +53,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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=ios + arguments: --headless --result=${{ github.workspace }}/TestResults.iOS.xml --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=ios-${{ github.run_id }}-${{ github.run_attempt }} - 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 201d1c26cc..c7d3b955ad 100755 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -40,7 +40,7 @@ jobs: env: apiKey: ${{ secrets.BaaSaasApiKey }} if: ${{ env.apiKey }} - run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=xamarinmacos + run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=xamarinmacos-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -48,7 +48,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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=xamarinmacos + run: Tests/Tests.XamarinMac/bin/Release/Tests.XamarinMac.app/Contents/MacOS/Tests.XamarinMac --headless --result=${{ github.workspace }}/TestResults.XamarinMac.xml --labels=All --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=xamarinmacos-${{ github.run_id }}-${{ github.run_attempt }} - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() @@ -93,7 +93,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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=maccatalyst-${{ github.run_id }}-${{ github.run_attempt }} - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b if: always() diff --git a/.github/workflows/test-net-framework.yml b/.github/workflows/test-net-framework.yml index 8c80f19921..6efd8f8e08 100755 --- a/.github/workflows/test-net-framework.yml +++ b/.github/workflows/test-net-framework.yml @@ -40,7 +40,7 @@ jobs: env: apiKey: ${{ secrets.BaaSaasApiKey }} if: ${{ env.apiKey }} - run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=net-framework + run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=net-framework-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps - name: Add msbuild to PATH uses: microsoft/setup-msbuild@0b44c6745b7e81956596964100aadb92d667c497 @@ -48,7 +48,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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=net-framework + run: ./Tests/Realm.Tests/bin/Release/net461/Realm.Tests.exe --result=TestResults.Windows.xml --labels=After --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=net-framework-${{ github.run_id }}-${{ github.run_attempt }} - 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 ff14b7aefc..d7463ab641 100755 --- a/.github/workflows/test-tvos.yml +++ b/.github/workflows/test-tvos.yml @@ -47,7 +47,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 --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=tvos + arguments: --headless --result=${{ github.workspace }}/TestResults.tvOS.xml --labels=All --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=tvos-${{ github.run_id }}-${{ github.run_attempt }} 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 64d13db9f3..69ad6ad743 100755 --- a/.github/workflows/test-uwp-managed.yml +++ b/.github/workflows/test-uwp-managed.yml @@ -44,7 +44,7 @@ jobs: env: apiKey: ${{ secrets.BaaSaasApiKey }} if: ${{ env.apiKey }} - run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=uwp-managed + run: dotnet run deploy-apps --baasaas-api-key=${{ secrets.BaaSaasApiKey }} --baas-differentiator=uwp-managed-${{ github.run_id }}-${{ github.run_attempt }} working-directory: Tools/DeployApps - name: Import test certificate run: | @@ -59,7 +59,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 ' --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=uwp-managed' + run: ./Tests/Tests.UWP/RunTests.ps1 -ExtraAppArgs ' --baasaas-api-key=${{ secrets.BaaSaasApiKey}} --baas-differentiator=uwp-managed-${{ github.run_id }}-${{ github.run_attempt }}' shell: powershell - name: Publish Unit Test Results uses: LaPeste/test-reporter@510caf50a955b1003bec48a6494be4d6537f3a0b diff --git a/Realm/Realm/DatabaseTypes/RealmValue.cs b/Realm/Realm/DatabaseTypes/RealmValue.cs index bd854963bd..0943fddb4a 100644 --- a/Realm/Realm/DatabaseTypes/RealmValue.cs +++ b/Realm/Realm/DatabaseTypes/RealmValue.cs @@ -1533,9 +1533,6 @@ public bool Equals(RealmValue other) RealmValueType.ObjectId => AsObjectId() == other.AsObjectId(), RealmValueType.Guid => AsGuid() == other.AsGuid(), RealmValueType.Object => AsIRealmObject().Equals(other.AsIRealmObject()), - // TODO Reconsider doing expensive elementwise comparison - RealmValueType.List => AsList().SequenceEqual(other.AsList()), - RealmValueType.Dictionary => AsDictionary().DictionaryEquals(other.AsDictionary()), RealmValueType.Null => true, _ => false, }; diff --git a/Realm/Realm/Extensions/CollectionExtensions.cs b/Realm/Realm/Extensions/CollectionExtensions.cs index d29168138d..b5c03acc89 100644 --- a/Realm/Realm/Extensions/CollectionExtensions.cs +++ b/Realm/Realm/Extensions/CollectionExtensions.cs @@ -569,11 +569,6 @@ public static void PopulateCollection(ICollection source, ICollection t public static void PopulateCollection(IDictionary source, IDictionary target, bool update, bool skipDefaults) => PopulateCollectionCore(source, target, update, skipDefaults, kvp => kvp.Value); - internal static bool DictionaryEquals(this IDictionary first, IDictionary second) - { - return first.Count == second.Count && first.All(fkv => second.TryGetValue(fkv.Key, out RealmValue sVal) && fkv.Value == sVal); - } - private static bool ShouldWaitForSync(WaitForSyncMode mode, Subscription? oldSub, Subscription newSub) { switch (mode) diff --git a/Tests/Realm.Tests/Database/RealmValueWithCollections.cs b/Tests/Realm.Tests/Database/RealmValueWithCollections.cs index 7c5731c740..ba21cd2aa5 100644 --- a/Tests/Realm.Tests/Database/RealmValueWithCollections.cs +++ b/Tests/Realm.Tests/Database/RealmValueWithCollections.cs @@ -27,8 +27,10 @@ namespace Realms.Tests.Database [TestFixture, Preserve(AllMembers = true)] internal class RealmValueWithCollections : RealmInstanceTest { - public static Func> ListGenerator = i => { return new List { $"inner{i}", i }; }; - public static Func> DictGenerator = i => { return new Dictionary { { "s1", i }, { "s2", $"ah{i}" } }; }; + private readonly RealmValueComparer _rvComparer = new(); + + public static Func> ListGenerator = i => new List { $"inner{i}", i }; + public static Func> DictGenerator = i => new Dictionary { { "s1", i }, { "s2", $"ah{i}" } }; public static Func[] CollectionGenerators = new Func[] { @@ -82,13 +84,44 @@ public void List_WhenRetrieved_WorksWithAllTypes([Values(true, false)] bool isMa Assert.That(rv.Type, Is.EqualTo(RealmValueType.List)); Assert.That(rv != RealmValue.Null); - Assert.That(rv.AsList(), Is.EqualTo(originalList)); - Assert.That(rv.AsAny(), Is.EqualTo(originalList)); - Assert.That(rv.As>(), Is.EqualTo(originalList)); + Assert.That(rv.AsList(), Is.EqualTo(originalList).Using(_rvComparer)); + Assert.That(rv.AsAny(), Is.EqualTo(originalList).Using(_rvComparer)); + Assert.That(rv.As>(), Is.EqualTo(originalList).Using(_rvComparer)); + } + + [Test] + public void List_InRealmValue_NotEqualToAnything([Values(true, false)] bool isManaged) + { + var innerList = ListGenerator(1); + var innerDict = DictGenerator(1); + + var originalList = new List + { + RealmValue.Null, + 1, + true, + "string", + new byte[] { 0, 1, 2 }, + new DateTimeOffset(1234, 5, 6, 7, 8, 9, TimeSpan.Zero), + 1f, + 2d, + 3m, + new ObjectId("5f63e882536de46d71877979"), + Guid.Parse("3809d6d9-7618-4b3d-8044-2aa35fd02f31"), + new InternalObject { IntProperty = 10, StringProperty = "brown" }, + innerList, + innerDict, + }; + + RealmValue rv = originalList; + + if (isManaged) + { + rv = PersistAndFind(rv).RealmValueProperty; + } - Assert.That(rv == originalList); - Assert.That(rv.Equals(originalList)); - Assert.That(rv.AsList().SequenceEqual(originalList)); + Assert.That(rv == originalList, Is.False); + Assert.That(rv.Equals(originalList), Is.False); } [Test] @@ -131,16 +164,7 @@ public void List_CanBeCopiedFromManagedList([Values(true, false)] bool isManaged var newObj = new RealmValueObject { RealmValueProperty = rv }; - RealmValue rv2; - - if (isManaged) - { - rv2 = PersistAndFind(rv).RealmValueProperty; - } - else - { - rv2 = newObj.RealmValueProperty; - } + var rv2 = isManaged ? PersistAndFind(rv).RealmValueProperty : newObj.RealmValueProperty; Assert.That(rv.AsList(), Is.EqualTo(rv2.AsList())); Assert.That(rv.AsList(), Is.EqualTo(originalList)); @@ -261,10 +285,7 @@ public void List_WhenManaged_CanBeModified() { var listVal = new List { 1, "string", true }; - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject { RealmValueProperty = listVal }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = listVal })); _realm.Write(() => { @@ -288,7 +309,7 @@ public void List_WhenManaged_CanBeModified() listVal.Add("newVal"); }); - Assert.That(rvo.RealmValueProperty.AsList(), Is.EqualTo(listVal)); + Assert.That(rvo.RealmValueProperty.AsList(), Is.EqualTo(listVal).Using(_rvComparer)); } [TestCaseSource(nameof(CollectionGenerators))] @@ -296,10 +317,7 @@ public void List_AddSetInsertMoveRemoveCollection_WorksAsIntended(Func { 1, "string", true }; - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject { RealmValueProperty = listVal }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = listVal })); // Indexer var c1 = collectionGenerator(1); @@ -310,7 +328,7 @@ public void List_AddSetInsertMoveRemoveCollection_WorksAsIntended(Func @@ -341,7 +359,7 @@ public void List_AddSetInsertMoveRemoveCollection_WorksAsIntended(Func @@ -350,7 +368,7 @@ public void List_AddSetInsertMoveRemoveCollection_WorksAsIntended(Func { innerList, innerDict }; - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject { RealmValueProperty = listVal }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = listVal })); _realm.Write(() => { @@ -383,10 +398,7 @@ public void List_WhenManaged_WorksWithDynamicLikeApi() { var originalList = ListGenerator(1); - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject()); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject())); _realm.Write(() => { @@ -405,10 +417,7 @@ public void List_WhenManaged_WorksWithDynamic() { var originalList = ListGenerator(1); - dynamic rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject()); - }); + dynamic rvo = _realm.Write(() => _realm.Add(new RealmValueObject())); _realm.Write(() => { @@ -425,13 +434,10 @@ public void List_WhenManaged_WorksWithNotifications() { var originalList = new List { 1, ListGenerator(1), DictGenerator(1) }; - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject { RealmValueProperty = originalList }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = originalList })); var callbacks = new List(); - using var token = rvo.RealmValueProperty.AsList().SubscribeForNotifications((collection, changes) => + using var token = rvo.RealmValueProperty.AsList().SubscribeForNotifications((_, changes) => { if (changes != null) { @@ -472,7 +478,7 @@ public void List_WhenManaged_WorksWithNotifications() callbacks.Clear(); } - + #endregion #region Dictionary @@ -511,12 +517,33 @@ public void Dictionary_WhenRetrieved_WorksWithAllTypes([Values(true, false)] boo Assert.That(rv.Type, Is.EqualTo(RealmValueType.Dictionary)); Assert.That(rv != RealmValue.Null, "Different than null"); - Assert.That(rv.AsDictionary(), Is.EquivalentTo(originalDict)); - Assert.That(rv.AsAny(), Is.EquivalentTo(originalDict)); - Assert.That(rv.As>(), Is.EquivalentTo(originalDict)); + Assert.That(rv.AsDictionary(), Is.EquivalentTo(originalDict).Using(_rvComparer)); + Assert.That(rv.AsAny(), Is.EquivalentTo(originalDict).Using(_rvComparer)); + Assert.That(rv.As>(), Is.EquivalentTo(originalDict).Using(_rvComparer)); + } + + [Test] + public void Dictionary_InRealmValue_NotEqualToAnything([Values(true, false)] bool isManaged) + { + var innerList = ListGenerator(1); + var innerDict = DictGenerator(1); + + var originalDict = new Dictionary + { + { "c", new InternalObject { IntProperty = 10, StringProperty = "brown" } }, + { "d", innerList }, + { "e", innerDict }, + }; + + RealmValue rv = originalDict; - Assert.That(rv == originalDict, "Equal to original dict"); - Assert.That(rv.Equals(originalDict), "Equal to original dict with Equals"); + if (isManaged) + { + rv = PersistAndFind(rv).RealmValueProperty; + } + + Assert.That(rv == originalDict, Is.False); + Assert.That(rv.Equals(originalDict), Is.False); } [Test] @@ -565,16 +592,7 @@ public void Dictionary_CanBeCopiedFromManagedDictionary([Values(true, false)] bo var newObj = new RealmValueObject { RealmValueProperty = rv }; - RealmValue rv2; - - if (isManaged) - { - rv2 = PersistAndFind(rv).RealmValueProperty; - } - else - { - rv2 = newObj.RealmValueProperty; - } + var rv2 = isManaged ? PersistAndFind(rv).RealmValueProperty : newObj.RealmValueProperty; Assert.That(rv.AsDictionary(), Is.EqualTo(rv2.AsDictionary())); Assert.That(rv.AsDictionary(), Is.EqualTo(originalDict)); @@ -665,10 +683,7 @@ public void Dictionary_WhenManaged_CanBeModified() { var dictVal = DictGenerator(1); - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject { RealmValueProperty = dictVal }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = dictVal })); _realm.Write(() => { @@ -700,10 +715,7 @@ public void Dictionary_AddSetInsertMoveRemoveCollection_WorksAsIntended(Func - { - return _realm.Add(new RealmValueObject { RealmValueProperty = dictVal }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = dictVal })); // Indexer var c1 = collectionGenerator(1); @@ -714,7 +726,7 @@ public void Dictionary_AddSetInsertMoveRemoveCollection_WorksAsIntended(Func @@ -734,13 +746,14 @@ public void Dictionary_AddSetInsertMoveRemoveCollection_WorksAsIntended(Func @@ -749,10 +762,7 @@ public void Dictionary_RemoveWithCollectionArgument_ReturnsFalse() { "s3", innerDict }, }; - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject { RealmValueProperty = dictVal }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = dictVal })); _realm.Write(() => { @@ -766,10 +776,7 @@ public void Dictionary_WhenManaged_WorksWithDynamicLikeApi() { var dictVal = DictGenerator(1); - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject()); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject())); _realm.Write(() => { @@ -788,10 +795,7 @@ public void Dictionary_WhenManaged_WorksWithDynamic() { var dictVal = DictGenerator(1); - dynamic rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject()); - }); + dynamic rvo = _realm.Write(() => _realm.Add(new RealmValueObject())); _realm.Write(() => { @@ -808,13 +812,10 @@ public void Dictionary_WhenManaged_WorksWithNotifications() { var dictVal = new Dictionary { { "s1", 1 }, { "s2", ListGenerator(1) }, { "s3", DictGenerator(1) } }; - var rvo = _realm.Write(() => - { - return _realm.Add(new RealmValueObject { RealmValueProperty = dictVal }); - }); + var rvo = _realm.Write(() => _realm.Add(new RealmValueObject { RealmValueProperty = dictVal })); var callbacks = new List(); - using var token = rvo.RealmValueProperty.AsDictionary().SubscribeForNotifications((collection, changes) => + using var token = rvo.RealmValueProperty.AsDictionary().SubscribeForNotifications((_, changes) => { if (changes != null) { @@ -940,16 +941,14 @@ public void IndexedRealmValue_WithCollection_BasicTest() innerDict, }; - var obj = _realm.Write(() => - { - return _realm.Add(new IndexedRealmValueObject { RealmValueProperty = originalList }); - }); + var obj = _realm.Write( + () => _realm.Add(new IndexedRealmValueObject { RealmValueProperty = originalList })); RealmValue rv = obj.RealmValueProperty; Assert.That(rv.Type, Is.EqualTo(RealmValueType.List)); Assert.That(rv != RealmValue.Null); - Assert.That(rv.AsList(), Is.EqualTo(originalList)); + Assert.That(rv.AsList(), Is.EqualTo(originalList).Using(_rvComparer)); var originalDict = new Dictionary { @@ -979,11 +978,36 @@ public void IndexedRealmValue_WithCollection_BasicTest() Assert.That(rv.Type, Is.EqualTo(RealmValueType.Dictionary)); Assert.That(rv != RealmValue.Null, "Different than null"); - Assert.That(rv.AsDictionary(), Is.EquivalentTo(originalDict)); - Assert.That(rv.AsAny(), Is.EquivalentTo(originalDict)); - Assert.That(rv.As>(), Is.EquivalentTo(originalDict)); + Assert.That(rv.AsDictionary(), Is.EqualTo(originalDict).Using(_rvComparer)); + Assert.That(rv.AsAny(), Is.EqualTo(originalDict).Using(_rvComparer)); + Assert.That(rv.As>(), Is.EqualTo(originalDict).Using(_rvComparer)); } #endregion + + private class RealmValueComparer : IEqualityComparer + { + public bool Equals(RealmValue x, RealmValue y) + { + return x.Type switch + { + RealmValueType.List => x.AsList().SequenceEqual(y.AsList(), this), + RealmValueType.Dictionary => DictionaryEquals(x.AsDictionary(), y.AsDictionary()), + _ => x.Equals(y) + }; + } + + public int GetHashCode(RealmValue obj) + { + return obj.GetHashCode(); + } + + private bool DictionaryEquals(IDictionary first, IDictionary second) + { + return first.Count == second.Count && + first.All(fkv => second.TryGetValue(fkv.Key, out RealmValue sVal) && + Equals(fkv.Value, sVal)); + } + } } }