@@ -2114,6 +2114,80 @@ mod tests {
21142114 Ok ( ( ) )
21152115 }
21162116
2117+ // Bug 2039791.
2118+ // Verifies that fetch_remote_tree fails with MissingParentForUnknownChild when
2119+ // moz_bookmarks_synced_structure has a row whose child and parent are both
2120+ // tombstoned (isDeleted=1, needsMerge=0). The FK on parentGuid is
2121+ // satisfied because tombstoned rows still exist in moz_bookmarks_synced.
2122+ #[ test]
2123+ fn test_fetch_remote_tree_with_tombstoned_structure_endpoints ( ) -> Result < ( ) > {
2124+ let api = new_mem_api ( ) ;
2125+ let db = api. get_sync_connection ( ) . unwrap ( ) ;
2126+ let conn = db. lock ( ) ;
2127+ let interrupt_scope = conn. begin_interrupt_scope ( ) ?;
2128+
2129+ conn. execute_batch ( & format ! (
2130+ "INSERT INTO moz_bookmarks_synced(guid, isDeleted, needsMerge, kind)
2131+ VALUES ('Pppppppppppp', 1, 0, {folder}),
2132+ ('Cccccccccccc', 1, 0, {bookmark});
2133+ INSERT INTO moz_bookmarks_synced_structure(guid, parentGuid, position)
2134+ VALUES ('Cccccccccccc', 'Pppppppppppp', 0);" ,
2135+ folder = SyncedBookmarkKind :: Folder as u8 ,
2136+ bookmark = SyncedBookmarkKind :: Bookmark as u8 ,
2137+ ) ) ?;
2138+
2139+ let merger = Merger :: new ( & conn, & interrupt_scope, ServerTimestamp ( 0 ) ) ;
2140+ let result = merger. fetch_remote_tree ( ) ;
2141+
2142+ assert ! (
2143+ matches!(
2144+ result,
2145+ Err ( Error :: MergeError ( ref e) )
2146+ if matches!( e. kind( ) , dogear:: ErrorKind :: MissingParentForUnknownChild ( ..) )
2147+ ) ,
2148+ "expected MissingParentForUnknownChild, got {:?}" ,
2149+ result
2150+ ) ;
2151+ Ok ( ( ) )
2152+ }
2153+
2154+ // Bug 2039791.
2155+ // Verifies that fetch_remote_tree fails with InvalidParent when
2156+ // moz_bookmarks_synced_structure has a row whose parentGuid refers to a
2157+ // non-folder (eg, kind=Bookmark). Both endpoints are inserted into the dogear
2158+ // builder, but dogear's by_children rejects a non-folder parent.
2159+ #[ test]
2160+ fn test_fetch_remote_tree_with_non_folder_parent_in_structure ( ) -> Result < ( ) > {
2161+ let api = new_mem_api ( ) ;
2162+ let db = api. get_sync_connection ( ) . unwrap ( ) ;
2163+ let conn = db. lock ( ) ;
2164+ let interrupt_scope = conn. begin_interrupt_scope ( ) ?;
2165+
2166+ conn. execute_batch ( & format ! (
2167+ "INSERT INTO moz_bookmarks_synced(guid, isDeleted, needsMerge, kind, validity)
2168+ VALUES ('Pppppppppppp', 0, 0, {bookmark}, {valid}),
2169+ ('Cccccccccccc', 0, 0, {bookmark}, {valid});
2170+ INSERT INTO moz_bookmarks_synced_structure(guid, parentGuid, position)
2171+ VALUES ('Cccccccccccc', 'Pppppppppppp', 0);" ,
2172+ bookmark = SyncedBookmarkKind :: Bookmark as u8 ,
2173+ valid = SyncedBookmarkValidity :: Valid as u8 ,
2174+ ) ) ?;
2175+
2176+ let merger = Merger :: new ( & conn, & interrupt_scope, ServerTimestamp ( 0 ) ) ;
2177+ let result = merger. fetch_remote_tree ( ) ;
2178+
2179+ assert ! (
2180+ matches!(
2181+ result,
2182+ Err ( Error :: MergeError ( ref e) )
2183+ if matches!( e. kind( ) , dogear:: ErrorKind :: InvalidParent ( ..) )
2184+ ) ,
2185+ "expected InvalidParent, got {:?}" ,
2186+ result
2187+ ) ;
2188+ Ok ( ( ) )
2189+ }
2190+
21172191 #[ test]
21182192 fn test_fetch_local_tree ( ) -> Result < ( ) > {
21192193 let now = SystemTime :: now ( ) ;
0 commit comments