@@ -844,4 +844,115 @@ TEST(Sync_SyncMetadataSchemaVersions_LegacyTable)
844844 }
845845}
846846
847+ TEST (Sync_MutableSubscriptionSetOperations)
848+ {
849+ SHARED_GROUP_TEST_PATH (sub_store_path);
850+ SubscriptionStoreFixture fixture (sub_store_path);
851+ auto store = SubscriptionStore::create (fixture.db , [](int64_t ) {});
852+
853+ auto read_tr = fixture.db ->start_read ();
854+ Query query_a (read_tr->get_table (" class_a" ));
855+ query_a.greater_equal (fixture.bar_col , int64_t (1 ));
856+ Query query_b (read_tr->get_table (fixture.a_table_key ));
857+ query_b.equal (fixture.foo_col , " Realm" );
858+ Query query_c (read_tr->get_table (fixture.a_table_key ));
859+
860+ // insert_or_assign
861+ {
862+ auto out = store->get_latest ().make_mutable_copy ();
863+ auto [it, inserted] = out.insert_or_assign (" a sub" , query_a);
864+ CHECK (inserted);
865+ auto named_id = it->id ;
866+ out.insert_or_assign (" b sub" , query_b);
867+ CHECK_EQUAL (out.size (), 2 );
868+ std::tie (it, inserted) = out.insert_or_assign (" a sub" , query_a);
869+ CHECK_NOT (inserted);
870+ CHECK_EQUAL (it->id , named_id);
871+ CHECK_EQUAL (out.size (), 2 );
872+ }
873+
874+ // find
875+ {
876+ auto out = store->get_latest ().make_mutable_copy ();
877+ auto [it, inserted] = out.insert_or_assign (" a sub" , query_a);
878+ std::tie (it, inserted) = out.insert_or_assign (" b sub" , query_b);
879+ CHECK (out.find (query_b));
880+ CHECK (out.find (" a sub" ));
881+ }
882+
883+ // erase
884+ {
885+ auto out = store->get_latest ().make_mutable_copy ();
886+ out.insert_or_assign (" a sub" , query_a);
887+ out.insert_or_assign (" b sub" , query_b);
888+ out.insert_or_assign (" c sub" , query_c);
889+ CHECK_EQUAL (out.size (), 3 );
890+ auto it = out.erase (out.begin ());
891+ // Iterator points to last query inserted due do "swap and pop" idiom.
892+ CHECK_EQUAL (it->query_string , query_c.get_description ());
893+ CHECK_EQUAL (out.size (), 2 );
894+ CHECK_NOT (out.erase (" a sub" ));
895+ CHECK_EQUAL (out.size (), 2 );
896+ CHECK (out.erase (query_b));
897+ CHECK_EQUAL (out.size (), 1 );
898+ CHECK (out.erase (" c sub" ));
899+ CHECK_EQUAL (out.size (), 0 );
900+ }
901+
902+ // erase_by_class_name
903+ {
904+ auto out = store->get_latest ().make_mutable_copy ();
905+ out.insert_or_assign (" a sub" , query_a);
906+ out.insert_or_assign (" b sub" , query_b);
907+ out.insert_or_assign (" c sub" , query_c);
908+ // Nothing to erase.
909+ CHECK_NOT (out.erase_by_class_name (" foo" ));
910+ // Erase all queries for the class type of the first query.
911+ CHECK (out.erase_by_class_name (out.begin ()->object_class_name ));
912+ // No queries left.
913+ CHECK_EQUAL (out.size (), 0 );
914+ }
915+
916+ // erase_by_id
917+ {
918+ auto out = store->get_latest ().make_mutable_copy ();
919+ out.insert_or_assign (" a sub" , query_a);
920+ out.insert_or_assign (" b sub" , query_b);
921+ // Nothing to erase.
922+ CHECK_NOT (out.erase_by_id (ObjectId::gen ()));
923+ // Erase first query.
924+ CHECK (out.erase_by_id (out.begin ()->id ));
925+ CHECK_EQUAL (out.size (), 1 );
926+ }
927+
928+ // clear
929+ {
930+ auto out = store->get_latest ().make_mutable_copy ();
931+ out.insert_or_assign (" a sub" , query_a);
932+ out.insert_or_assign (" b sub" , query_b);
933+ out.insert_or_assign (" c sub" , query_c);
934+ CHECK_EQUAL (out.size (), 3 );
935+ out.clear ();
936+ CHECK_EQUAL (out.size (), 0 );
937+ }
938+
939+ // import
940+ {
941+ auto out = store->get_latest ().make_mutable_copy ();
942+ out.insert_or_assign (" a sub" , query_a);
943+ out.insert_or_assign (" b sub" , query_b);
944+ auto subs = out.commit ();
945+
946+ // This is an empty subscription set.
947+ auto out2 = store->get_active ().make_mutable_copy ();
948+ out2.insert_or_assign (" c sub" , query_c);
949+ out2.import (subs);
950+ // "c sub" is erased when 'import' is used.
951+ CHECK_EQUAL (out2.size (), 2 );
952+ // insert "c sub" again.
953+ out2.insert_or_assign (" c sub" , query_c);
954+ CHECK_EQUAL (out2.size (), 3 );
955+ }
956+ }
957+
847958} // namespace realm::sync
0 commit comments