@@ -1098,7 +1098,7 @@ TEST(List_UpdateIfNeeded)
10981098 auto table = tr->add_table (" table" );
10991099 auto col = table->add_column (type_Mixed, " mixed" );
11001100 auto col2 = table->add_column (type_Mixed, " col2" );
1101- table->create_object ();
1101+ auto leading_obj = table->create_object ();
11021102 Obj obj = table->create_object ();
11031103 obj.set_collection (col, CollectionType::List);
11041104
@@ -1123,9 +1123,24 @@ TEST(List_UpdateIfNeeded)
11231123 // The list is now non-empty, so a new accessor can initialize
11241124 auto list_3 = obj.get_list <Mixed>(col);
11251125 CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
1126+ CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::NoChange);
1127+
1128+ // A copy of a list is lazily initialized, so it's updated on first call
1129+ // even if the source was up-to-date
1130+ auto list_4 = std::make_shared<Lst<Mixed>>(list_3);
1131+ CHECK_EQUAL (list_4->update_if_needed (), UpdateStatus::Updated);
1132+
1133+ // Nested lists work the same way as top-level ones
1134+ list_4->insert_collection (1 , CollectionType::List);
1135+ auto list_4_1 = list_4->get_list (1 );
1136+ auto list_4_2 = list_4->get_list (1 );
1137+ list_4_1->add (Mixed ());
1138+ // FIXME: this should be NoChange
1139+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1140+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
11261141
11271142 // Update the row index of the parent object, forcing it to update
1128- table-> remove_object (table-> begin () );
1143+ leading_obj. remove ( );
11291144
11301145 // Updating the base object directly first doesn't change the result of
11311146 // updating the list
@@ -1135,6 +1150,12 @@ TEST(List_UpdateIfNeeded)
11351150 CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Updated);
11361151 CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
11371152
1153+ // These two lists share the same parent, so the first updates due to the
1154+ // parent returning Updated, and the second updates due to seeing that the
1155+ // parent version has changed
1156+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1157+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
1158+
11381159 tr->commit_and_continue_as_read ();
11391160
11401161 // Committing the write transaction changes the obj's ref, so everything
@@ -1143,6 +1164,8 @@ TEST(List_UpdateIfNeeded)
11431164 CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::Updated);
11441165 CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Updated);
11451166 CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
1167+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1168+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
11461169
11471170 // Perform a write which does not result in obj changing
11481171 {
@@ -1157,6 +1180,8 @@ TEST(List_UpdateIfNeeded)
11571180 CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::NoChange);
11581181 CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::NoChange);
11591182 CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::NoChange);
1183+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::NoChange);
1184+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::NoChange);
11601185
11611186 // Perform a write which does modify obj
11621187 {
@@ -1171,6 +1196,8 @@ TEST(List_UpdateIfNeeded)
11711196 CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::Updated);
11721197 CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Updated);
11731198 CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
1199+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1200+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
11741201
11751202 // Everything updates to detached when the object is removed
11761203 tr->promote_to_write ();
@@ -1180,4 +1207,41 @@ TEST(List_UpdateIfNeeded)
11801207 CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::Detached);
11811208 CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Detached);
11821209 CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Detached);
1210+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Detached);
1211+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Detached);
1212+ }
1213+
1214+ TEST (List_AsCollectionParent)
1215+ {
1216+ Group g;
1217+ auto table = g.add_table (" table" );
1218+ auto col = table->add_column (type_Mixed, " mixed" );
1219+
1220+ Obj obj = table->create_object ();
1221+ obj.set_collection (col, CollectionType::List);
1222+ auto list_1 = obj.get_list <Mixed>(col);
1223+ list_1.insert_collection (0 , CollectionType::List);
1224+
1225+ // list_1 is stack allocated, so we have to create a new object which can
1226+ // serve as the owner. This object is not reused for multiple calls.
1227+ auto list_1_1 = list_1.get_list (0 );
1228+ auto list_1_2 = list_1.get_list (0 );
1229+ CHECK_NOT_EQUAL (list_1_1->get_owner (), &list_1);
1230+ CHECK_NOT_EQUAL (list_1_1->get_owner (), list_1_2->get_owner ());
1231+
1232+ // list_2 is heap allocated but not owned by a shared_ptr, so we have to
1233+ // create a new object which can serve as the owner. This object is not
1234+ // reused for multiple calls.
1235+ auto list_2 = obj.get_list_ptr <Mixed>(col);
1236+ auto list_2_1 = list_2->get_list (0 );
1237+ auto list_2_2 = list_2->get_list (0 );
1238+ CHECK_NOT_EQUAL (list_2_1->get_owner (), list_2.get ());
1239+ CHECK_NOT_EQUAL (list_2_1->get_owner (), list_2_2->get_owner ());
1240+
1241+ // list_3 is owned by a shared_ptr, so we can just use it as the owner directly
1242+ auto list_3 = std::shared_ptr{std::move (list_2)};
1243+ auto list_3_1 = list_3->get_list (0 );
1244+ auto list_3_2 = list_3->get_list (0 );
1245+ CHECK_EQUAL (list_3_1->get_owner (), list_3.get ());
1246+ CHECK_EQUAL (list_3_1->get_owner (), list_3_2->get_owner ());
11831247}
0 commit comments