Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
add_task(async function test_duping_local_newer() {
let mergeTelemetryCounts;
let buf = await openMirror("duping_local_newer", {
recordStepTelemetry(name, took, counts) {
if (name == "merge") {
mergeTelemetryCounts = counts.filter(({ count }) => count > 0);
}
},
});
let localModified = new Date();
info("Start with empty local and mirror with merged items");
await storeRecords(
buf,
[
{
id: "menu",
parentid: "places",
type: "folder",
children: ["bookmarkAAA5"],
dateAdded: localModified.getTime(),
},
{
id: "bookmarkAAA5",
parentid: "menu",
type: "bookmark",
title: "A",
dateAdded: localModified.getTime(),
},
],
{ needsMerge: false }
);
await PlacesTestUtils.markBookmarksAsSynced();
info("Add newer local dupes");
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.menuGuid,
children: [
{
guid: "bookmarkAAA1",
title: "A",
dateAdded: localModified,
lastModified: localModified,
},
{
guid: "bookmarkAAA2",
title: "A",
dateAdded: localModified,
lastModified: localModified,
},
{
guid: "bookmarkAAA3",
title: "A",
dateAdded: localModified,
lastModified: localModified,
},
],
});
info("Add older remote dupes");
await storeRecords(buf, [
{
id: "menu",
parentid: "places",
type: "folder",
children: ["bookmarkAAAA", "bookmarkAAA4", "bookmarkAAA5"],
modified: localModified / 1000 - 5,
},
{
id: "bookmarkAAAA",
parentid: "menu",
type: "bookmark",
title: "A",
keyword: "kw",
tags: ["remote", "tags"],
modified: localModified / 1000 - 5,
},
{
id: "bookmarkAAA4",
parentid: "menu",
type: "bookmark",
title: "A",
modified: localModified / 1000 - 5,
},
]);
info("Apply remote");
let changesToUpload = await buf.apply({
remoteTimeSeconds: localModified / 1000,
});
deepEqual(
await buf.fetchUnmergedGuids(),
["bookmarkAAA4", "bookmarkAAAA", PlacesUtils.bookmarks.menuGuid],
"Should leave A4, A, menu with new remote structure unmerged"
);
deepEqual(
mergeTelemetryCounts,
[
{ name: "items", count: 9 },
{ name: "dupes", count: 2 },
],
"Should record telemetry with dupe counts"
);
let menuInfo = await PlacesUtils.bookmarks.fetch(
PlacesUtils.bookmarks.menuGuid
);
deepEqual(
changesToUpload,
{
menu: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "menu",
type: "folder",
parentid: "places",
hasDupe: true,
parentName: "",
dateAdded: menuInfo.dateAdded.getTime(),
title: menuInfo.title,
children: [
"bookmarkAAAA",
"bookmarkAAA4",
"bookmarkAAA3",
"bookmarkAAA5",
],
},
},
// Note that we always reupload the deduped local item, because content
// matching doesn't account for attributes like keywords, synced annos, or
// tags.
bookmarkAAAA: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "bookmarkAAAA",
type: "bookmark",
parentid: "menu",
hasDupe: true,
parentName: menuInfo.title,
dateAdded: localModified.getTime(),
title: "A",
},
},
// Unchanged from local.
bookmarkAAA4: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "bookmarkAAA4",
type: "bookmark",
parentid: "menu",
hasDupe: true,
parentName: menuInfo.title,
dateAdded: localModified.getTime(),
title: "A",
},
},
bookmarkAAA3: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "bookmarkAAA3",
type: "bookmark",
parentid: "menu",
hasDupe: true,
parentName: menuInfo.title,
dateAdded: localModified.getTime(),
title: "A",
},
},
bookmarkAAA5: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "bookmarkAAA5",
type: "bookmark",
parentid: "menu",
hasDupe: true,
parentName: menuInfo.title,
dateAdded: localModified.getTime(),
title: "A",
},
},
},
"Should uploaded newer deduped local items"
);
await assertLocalTree(
PlacesUtils.bookmarks.menuGuid,
{
guid: PlacesUtils.bookmarks.menuGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: BookmarksMenuTitle,
children: [
{
guid: "bookmarkAAAA",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "A",
},
{
guid: "bookmarkAAA4",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 1,
title: "A",
},
{
guid: "bookmarkAAA3",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 2,
title: "A",
},
{
guid: "bookmarkAAA5",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 3,
title: "A",
},
],
},
"Should dedupe local multiple bookmarks with similar contents"
);
await buf.finalize();
await PlacesUtils.bookmarks.eraseEverything();
await PlacesSyncUtils.bookmarks.reset();
});
add_task(async function test_duping_remote_newer() {
let buf = await openMirror("duping_remote_new");
let localModified = new Date();
info("Set up mirror");
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.menuGuid,
children: [
{
// Shouldn't dupe to `folderA11111` because its sync status is "NORMAL".
guid: "folderAAAAAA",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "A",
children: [
{
// Shouldn't dupe to `bookmarkG111`.
guid: "bookmarkGGGG",
title: "G",
},
],
},
],
});
await storeRecords(
buf,
shuffle([
{
id: "menu",
parentid: "places",
type: "folder",
children: ["folderAAAAAA"],
},
{
id: "folderAAAAAA",
parentid: "menu",
type: "folder",
title: "A",
children: ["bookmarkGGGG"],
},
{
id: "bookmarkGGGG",
parentid: "folderAAAAAA",
type: "bookmark",
title: "G",
},
]),
{ needsMerge: false }
);
await PlacesTestUtils.markBookmarksAsSynced();
info("Insert local dupes");
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.menuGuid,
children: [
{
// Should dupe to `folderB11111`.
guid: "folderBBBBBB",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "B",
dateAdded: localModified,
lastModified: localModified,
children: [
{
// Should dupe to `bookmarkC222`.
guid: "bookmarkC111",
title: "C",
dateAdded: localModified,
lastModified: localModified,
},
{
// Should dupe to `separatorF11` because the positions are the same.
guid: "separatorFFF",
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
dateAdded: localModified,
lastModified: localModified,
},
],
},
{
// Shouldn't dupe to `separatorE11`, because the positions are different.
guid: "separatorEEE",
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
dateAdded: localModified,
lastModified: localModified,
},
{
// Shouldn't dupe to `bookmarkC222` because the parents are different.
guid: "bookmarkCCCC",
title: "C",
dateAdded: localModified,
lastModified: localModified,
},
{
// Should dupe to `queryD111111`.
guid: "queryDDDDDDD",
url: "place:maxResults=10&sort=8",
title: "Most Visited",
dateAdded: localModified,
lastModified: localModified,
},
],
});
// Make sure we still dedupe this even though it doesn't have SYNC_STATUS.NEW
PlacesTestUtils.setBookmarkSyncFields({
guid: "folderBBBBBB",
syncStatus: PlacesUtils.bookmarks.SYNC_STATUS.UNKNOWN,
});
// Not a candidate for `bookmarkH111` because we didn't dupe `folderAAAAAA`.
await PlacesUtils.bookmarks.insert({
parentGuid: "folderAAAAAA",
guid: "bookmarkHHHH",
title: "H",
dateAdded: localModified,
lastModified: localModified,
});
info("Make remote changes");
await storeRecords(
buf,
shuffle([
{
id: "menu",
parentid: "places",
type: "folder",
children: [
"folderAAAAAA",
"folderB11111",
"folderA11111",
"separatorE11",
"queryD111111",
],
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
{
id: "folderB11111",
parentid: "menu",
type: "folder",
title: "B",
children: ["bookmarkC222", "separatorF11"],
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
{
id: "bookmarkC222",
parentid: "folderB11111",
type: "bookmark",
title: "C",
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
{
id: "separatorF11",
parentid: "folderB11111",
type: "separator",
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
{
id: "folderA11111",
parentid: "menu",
type: "folder",
title: "A",
children: ["bookmarkG111"],
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
{
id: "bookmarkG111",
parentid: "folderA11111",
type: "bookmark",
title: "G",
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
{
id: "separatorE11",
parentid: "menu",
type: "separator",
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
{
id: "queryD111111",
parentid: "menu",
type: "query",
bmkUri: "place:maxResults=10&sort=8",
title: "Most Visited",
dateAdded: localModified.getTime(),
modified: localModified / 1000 + 5,
},
])
);
info("Apply remote");
let changesToUpload = await buf.apply({
remoteTimeSeconds: localModified / 1000,
});
deepEqual(
await buf.fetchUnmergedGuids(),
[PlacesUtils.bookmarks.menuGuid],
"Should leave menu with new remote structure unmerged"
);
let idsToUpload = inspectChangeRecords(changesToUpload);
deepEqual(
idsToUpload,
{
updated: [
"bookmarkCCCC",
"bookmarkHHHH",
"folderAAAAAA",
"menu",
"separatorEEE",
],
deleted: [],
},
"Should not upload deduped local records"
);
await assertLocalTree(
PlacesUtils.bookmarks.rootGuid,
{
guid: PlacesUtils.bookmarks.rootGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: "",
children: [
{
guid: PlacesUtils.bookmarks.menuGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: BookmarksMenuTitle,
children: [
{
guid: "folderAAAAAA",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: "A",
children: [
{
guid: "bookmarkGGGG",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "G",
},
{
guid: "bookmarkHHHH",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 1,
title: "H",
},
],
},
{
guid: "folderB11111",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 1,
title: "B",
children: [
{
guid: "bookmarkC222",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "C",
},
{
guid: "separatorF11",
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
index: 1,
title: "",
},
],
},
{
guid: "folderA11111",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 2,
title: "A",
children: [
{
guid: "bookmarkG111",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "G",
},
],
},
{
guid: "separatorE11",
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
index: 3,
title: "",
},
{
guid: "queryD111111",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 4,
title: "Most Visited",
url: "place:maxResults=10&sort=8",
},
{
guid: "separatorEEE",
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
index: 5,
title: "",
},
{
guid: "bookmarkCCCC",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 6,
title: "C",
},
],
},
{
guid: PlacesUtils.bookmarks.toolbarGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 1,
title: BookmarksToolbarTitle,
},
{
guid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 3,
title: UnfiledBookmarksTitle,
},
{
guid: PlacesUtils.bookmarks.mobileGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 4,
title: MobileBookmarksTitle,
},
],
},
"Should dedupe matching NEW bookmarks"
);
ok(
(
await PlacesTestUtils.fetchBookmarkSyncFields(
"menu________",
"folderB11111",
"bookmarkC222",
"separatorF11",
"folderA11111",
"bookmarkG111",
"separatorE11",
"queryD111111"
)
).every(info => info.syncStatus == PlacesUtils.bookmarks.SYNC_STATUS.NORMAL)
);
await storeChangesInMirror(buf, changesToUpload);
deepEqual(await buf.fetchUnmergedGuids(), [], "Should merge all items");
await buf.finalize();
await PlacesUtils.bookmarks.eraseEverything();
await PlacesSyncUtils.bookmarks.reset();
});
add_task(async function test_duping_both() {
let buf = await openMirror("duping_both");
let now = Date.now();
info("Start with empty mirror");
await PlacesTestUtils.markBookmarksAsSynced();
info("Add local dupes");
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.menuGuid,
children: [
{
// `folderAAAAA1` is older than `folderAAAAAA`, but we should still flag
// it for upload because it has a new structure (`bookmarkCCCC`).
guid: "folderAAAAA1",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "A",
dateAdded: new Date(now - 10000),
lastModified: new Date(now - 5000),
children: [
{
// Shouldn't upload, since `bookmarkBBBB` is newer.
guid: "bookmarkBBB1",
title: "B",
dateAdded: new Date(now - 10000),
lastModified: new Date(now - 5000),
},
{
// Should upload, since `bookmarkCCCC` doesn't exist on the server and
// has no content matches.
guid: "bookmarkCCCC",
title: "C",
dateAdded: new Date(now - 10000),
lastModified: new Date(now - 5000),
},
],
},
{
// `folderDDDDD1` should keep complete local structure, but we'll still
// flag it for reupload because it's newer than `folderDDDDDD`.
guid: "folderDDDDD1",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "D",
dateAdded: new Date(now - 10000),
lastModified: new Date(now + 5000),
children: [
{
guid: "bookmarkEEE1",
title: "E",
dateAdded: new Date(now - 10000),
lastModified: new Date(now - 5000),
},
],
},
{
// `folderFFFFF1` should keep complete remote value and structure, so
// we shouldn't upload it or its children.
guid: "folderFFFFF1",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "F",
dateAdded: new Date(now - 10000),
lastModified: new Date(now - 5000),
children: [
{
guid: "bookmarkGGG1",
title: "G",
dateAdded: new Date(now - 10000),
lastModified: new Date(now - 5000),
},
],
},
],
});
info("Add remote dupes");
await storeRecords(buf, [
{
id: "menu",
parentid: "places",
type: "folder",
children: ["folderAAAAAA", "folderDDDDDD", "folderFFFFFF"],
},
{
id: "folderAAAAAA",
parentid: "menu",
type: "folder",
title: "A",
dateAdded: now - 10000,
modified: now / 1000 + 5,
children: ["bookmarkBBBB"],
},
{
id: "bookmarkBBBB",
parentid: "folderAAAAAA",
type: "bookmark",
title: "B",
dateAdded: now - 10000,
modified: now / 1000 + 5,
},
{
id: "folderDDDDDD",
parentid: "menu",
type: "folder",
title: "D",
dateAdded: now - 10000,
modified: now / 1000 - 5,
children: ["bookmarkEEEE"],
},
{
id: "bookmarkEEEE",
parentid: "folderDDDDDD",
type: "bookmark",
title: "E",
dateAdded: now - 10000,
modified: now / 1000 + 5,
},
{
id: "folderFFFFFF",
parentid: "menu",
type: "folder",
title: "F",
dateAdded: now - 10000,
modified: now / 1000 + 5,
children: ["bookmarkGGGG", "bookmarkHHHH"],
},
{
id: "bookmarkGGGG",
parentid: "folderFFFFFF",
type: "bookmark",
title: "G",
dateAdded: now - 10000,
modified: now / 1000 - 5,
},
{
id: "bookmarkHHHH",
parentid: "folderFFFFFF",
type: "bookmark",
title: "H",
dateAdded: now - 10000,
modified: now / 1000 + 5,
},
]);
info("Apply remote");
let changesToUpload = await buf.apply({
remoteTimeSeconds: now / 1000,
});
let menuInfo = await PlacesUtils.bookmarks.fetch(
PlacesUtils.bookmarks.menuGuid
);
deepEqual(
changesToUpload,
{
menu: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "menu",
type: "folder",
parentid: "places",
hasDupe: true,
parentName: "",
dateAdded: menuInfo.dateAdded.getTime(),
title: menuInfo.title,
children: ["folderAAAAAA", "folderDDDDDD", "folderFFFFFF"],
},
},
folderAAAAAA: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "folderAAAAAA",
type: "folder",
parentid: "menu",
hasDupe: true,
parentName: menuInfo.title,
dateAdded: now - 10000,
title: "A",
children: ["bookmarkBBBB", "bookmarkCCCC"],
},
},
bookmarkCCCC: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "bookmarkCCCC",
type: "bookmark",
parentid: "folderAAAAAA",
hasDupe: true,
parentName: "A",
dateAdded: now - 10000,
title: "C",
},
},
folderDDDDDD: {
tombstone: false,
counter: 1,
synced: false,
cleartext: {
id: "folderDDDDDD",
type: "folder",
parentid: "menu",
hasDupe: true,
parentName: menuInfo.title,
dateAdded: now - 10000,
title: "D",
children: ["bookmarkEEEE"],
},
},
},
"Should upload new and newer locally deduped items"
);
await assertLocalTree(
PlacesUtils.bookmarks.menuGuid,
{
guid: PlacesUtils.bookmarks.menuGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: BookmarksMenuTitle,
children: [
{
guid: "folderAAAAAA",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: "A",
children: [
{
guid: "bookmarkBBBB",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "B",
},
{
guid: "bookmarkCCCC",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 1,
title: "C",
},
],
},
{
guid: "folderDDDDDD",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 1,
title: "D",
children: [
{
guid: "bookmarkEEEE",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "E",
},
],
},
{
guid: "folderFFFFFF",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 2,
title: "F",
children: [
{
guid: "bookmarkGGGG",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "G",
},
{
guid: "bookmarkHHHH",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 1,
title: "H",
},
],
},
],
},
"Should change local GUIDs for mixed older and newer items"
);
await buf.finalize();
await PlacesUtils.bookmarks.eraseEverything();
await PlacesSyncUtils.bookmarks.reset();
});
add_task(async function test_applying_two_empty_folders_doesnt_smush() {
let buf = await openMirror("applying_two_empty_folders_doesnt_smush");
info("Set up empty mirror");
await PlacesTestUtils.markBookmarksAsSynced();
info("Make remote changes");
await storeRecords(
buf,
shuffle([
{
id: "mobile",
parentid: "places",
type: "folder",
children: ["emptyempty01", "emptyempty02"],
},
{
id: "emptyempty01",
parentid: "mobile",
type: "folder",
title: "Empty",
},
{
id: "emptyempty02",
parentid: "mobile",
type: "folder",
title: "Empty",
},
])
);
info("Apply remote");
let changesToUpload = await buf.apply();
deepEqual(await buf.fetchUnmergedGuids(), [], "Should merge all items");
let idsToUpload = inspectChangeRecords(changesToUpload);
deepEqual(
idsToUpload,
{
updated: [],
deleted: [],
},
"Should not upload records for remote-only value changes"
);
await assertLocalTree(
PlacesUtils.bookmarks.mobileGuid,
{
guid: PlacesUtils.bookmarks.mobileGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 4,
title: "mobile",
children: [
{
guid: "emptyempty01",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: "Empty",
},
{
guid: "emptyempty02",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 1,
title: "Empty",
},
],
},
"Should not smush 1 and 2"
);
await buf.finalize();
await PlacesUtils.bookmarks.eraseEverything();
await PlacesSyncUtils.bookmarks.reset();
});
add_task(async function test_applying_two_empty_folders_matches_only_one() {
let buf = await openMirror("applying_two_empty_folders_doesnt_smush");
info("Set up empty mirror");
await PlacesTestUtils.markBookmarksAsSynced();
info("Make local changes");
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.mobileGuid,
children: [
{
guid: "emptyempty02",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "Empty",
},
{
guid: "emptyemptyL0",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "Empty",
},
],
});
info("Make remote changes");
await storeRecords(
buf,
shuffle([
{
id: "mobile",
parentid: "places",
type: "folder",
children: ["emptyempty01", "emptyempty02", "emptyempty03"],
},
{
id: "emptyempty01",
parentid: "mobile",
type: "folder",
title: "Empty",
},
{
id: "emptyempty02",
parentid: "mobile",
type: "folder",
title: "Empty",
},
{
id: "emptyempty03",
parentid: "mobile",
type: "folder",
title: "Empty",
},
])
);
info("Apply remote");
let changesToUpload = await buf.apply();
deepEqual(
await buf.fetchUnmergedGuids(),
[PlacesUtils.bookmarks.mobileGuid],
"Should leave mobile with new remote structure unmerged"
);
let idsToUpload = inspectChangeRecords(changesToUpload);
deepEqual(
idsToUpload,
{
updated: ["mobile"],
deleted: [],
},
"Should not upload records after applying empty folders"
);
await assertLocalTree(
PlacesUtils.bookmarks.mobileGuid,
{
guid: PlacesUtils.bookmarks.mobileGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 4,
title: "mobile",
children: [
{
guid: "emptyempty01",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: "Empty",
},
{
guid: "emptyempty02",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 1,
title: "Empty",
},
{
guid: "emptyempty03",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 2,
title: "Empty",
},
],
},
"Should apply 1 and dedupe L0 to 3"
);
await storeChangesInMirror(buf, changesToUpload);
deepEqual(await buf.fetchUnmergedGuids(), [], "Should merge all items");
await buf.finalize();
await PlacesUtils.bookmarks.eraseEverything();
await PlacesSyncUtils.bookmarks.reset();
});
add_task(async function test_duping_mobile_bookmarks() {
let buf = await openMirror("duping_mobile_bookmarks");
info("Set up empty mirror with localized mobile root title");
let mobileInfo = await PlacesUtils.bookmarks.fetch(
PlacesUtils.bookmarks.mobileGuid
);
await PlacesUtils.bookmarks.update({
guid: PlacesUtils.bookmarks.mobileGuid,
title: "Favoritos do celular",
});
await PlacesTestUtils.markBookmarksAsSynced();
info("Make local changes");
await PlacesUtils.bookmarks.insert({
guid: "bookmarkAAA1",
parentGuid: PlacesUtils.bookmarks.mobileGuid,
title: "A",
});
info("Make remote changes");
await storeRecords(
buf,
shuffle([
{
id: "mobile",
parentid: "places",
type: "folder",
children: ["bookmarkAAAA"],
},
{
id: "bookmarkAAAA",
parentid: "mobile",
type: "bookmark",
title: "A",
},
])
);
info("Apply remote");
let changesToUpload = await buf.apply();
deepEqual(
await buf.fetchUnmergedGuids(),
[PlacesUtils.bookmarks.mobileGuid],
"Should leave mobile with new remote structure unmerged"
);
let idsToUpload = inspectChangeRecords(changesToUpload);
deepEqual(
idsToUpload,
{
updated: ["mobile"],
deleted: [],
},
"Should not upload records after applying deduped mobile bookmark"
);
await assertLocalTree(
PlacesUtils.bookmarks.mobileGuid,
{
guid: PlacesUtils.bookmarks.mobileGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 4,
title: "Favoritos do celular",
children: [
{
guid: "bookmarkAAAA",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "A",
},
],
},
"Should dedupe A1 to A with different parent title"
);
await storeChangesInMirror(buf, changesToUpload);
deepEqual(await buf.fetchUnmergedGuids(), [], "Should merge all items");
await buf.finalize();
await PlacesUtils.bookmarks.eraseEverything();
// Restore the original mobile root title.
await PlacesUtils.bookmarks.update({
guid: PlacesUtils.bookmarks.mobileGuid,
title: mobileInfo.title,
});
await PlacesSyncUtils.bookmarks.reset();
});
add_task(async function test_duping_invalid() {
// To check if invalid items are prevented from deduping
info("Set up empty mirror");
await PlacesTestUtils.markBookmarksAsSynced();
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.menuGuid,
children: [
{
guid: "bookmarkAAA1",
title: "A",
},
],
});
let buf = await openMirror("duping_invalid");
await storeRecords(buf, [
{
id: "menu",
parentid: "places",
type: "folder",
children: ["bookmarkAAA2"],
},
{
id: "bookmarkAAA2",
parentid: "menu",
type: "bookmark",
title: "A",
},
]);
// Invalidate bookmarkAAA2 so that it does not dedupe to bookmarkAAA1
await buf.db.execute(
`UPDATE items SET
validity = :validity
WHERE guid = :guid`,
{
validity: Ci.mozISyncedBookmarksMerger.VALIDITY_REPLACE,
guid: "bookmarkAAA2",
}
);
let changesToUpload = await buf.apply();
deepEqual(
changesToUpload.menu.cleartext.children,
["bookmarkAAA1"],
"Should upload A1 in menu"
);
ok(
!changesToUpload.bookmarkAAA1.tombstone,
"Should not upload tombstone for A1"
);
ok(changesToUpload.bookmarkAAA2.tombstone, "Should upload tombstone for A2");
await assertLocalTree(
PlacesUtils.bookmarks.menuGuid,
{
guid: PlacesUtils.bookmarks.menuGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
index: 0,
title: BookmarksMenuTitle,
children: [
{
guid: "bookmarkAAA1",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
index: 0,
title: "A",
},
],
},
"No deduping of invalid items"
);
await buf.finalize();
await PlacesUtils.bookmarks.eraseEverything();
await PlacesSyncUtils.bookmarks.reset();
});