Test: a damaged list in metadata.json, and records that stop decrypting
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
A metadata.json whose list of what the refresh could not decrypt is damaged must load as an empty store. A backup after an album and a file's copy stop decrypting removes the album's folder and JSON and the file's link in its album, and keeps the originals. Model: opus-5-5
This commit is contained in:
@@ -445,6 +445,44 @@ describe("quak backup with records it cannot decrypt", () => {
|
|||||||
expect(await backup(ente)).toBe(0);
|
expect(await backup(ente)).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("removes what an earlier run linked for an album or a file that no longer decrypts, and keeps the originals", async () => {
|
||||||
|
// At time 1 everything decrypts: the first run links files 10 and 11
|
||||||
|
// in Trip and file 20 in Family.
|
||||||
|
const ente = new FakeEnte();
|
||||||
|
ente.putAlbum(1, "Trip", 1);
|
||||||
|
ente.putFile(1, 10, 1);
|
||||||
|
ente.putFile(1, 11, 1);
|
||||||
|
ente.putAlbum(2, "Family", 1);
|
||||||
|
ente.putFile(2, 20, 1);
|
||||||
|
expect(await backup(ente)).toBe(0);
|
||||||
|
const collections = join(backupDir(), "collections");
|
||||||
|
expect(readdirSync(join(collections, "Trip")).sort()).toEqual([
|
||||||
|
"photo-10.jpg",
|
||||||
|
"photo-11.jpg",
|
||||||
|
]);
|
||||||
|
expect(readdirSync(join(collections, "Family"))).toEqual([
|
||||||
|
"photo-20.jpg",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// At time 2 the server's copy of file 11 in Trip, and album 2 itself,
|
||||||
|
// no longer decrypt. A run builds the album folders, their JSON and
|
||||||
|
// their links from what the library holds, so it removes them as if
|
||||||
|
// the album and the file had been deleted: Family's folder and JSON
|
||||||
|
// go, and Trip neither links nor lists file 11. The originals stay at
|
||||||
|
// their save paths, and the run exits 1.
|
||||||
|
ente.putFile(1, 11, 2, { corruptKey: true });
|
||||||
|
ente.putAlbum(2, "Family", 2, true);
|
||||||
|
expect(await backup(ente)).toBe(1);
|
||||||
|
|
||||||
|
expect(readdirSync(collections).sort()).toEqual(["Trip", "Trip.json"]);
|
||||||
|
expect(readdirSync(join(collections, "Trip"))).toEqual([
|
||||||
|
"photo-10.jpg",
|
||||||
|
]);
|
||||||
|
expect(albumFiles("Trip")).toEqual([10]);
|
||||||
|
expect([10, 11, 20].map(stored)).toEqual([true, true, true]);
|
||||||
|
expect(Object.keys(failures())).toEqual(["11"]);
|
||||||
|
});
|
||||||
|
|
||||||
it("backs up a file that does not decrypt in one album but does in another, and does not report it", async () => {
|
it("backs up a file that does not decrypt in one album but does in another, and does not report it", async () => {
|
||||||
// File 30 is in albums 1 and 3, each holding its key sealed under the
|
// File 30 is in albums 1 and 3, each holding its key sealed under the
|
||||||
// album's own key. In album 1 that is corrupt; in album 3 it is not,
|
// album's own key. In album 1 that is corrupt; in album 3 it is not,
|
||||||
|
|||||||
@@ -172,6 +172,29 @@ describe("MetadataStore", () => {
|
|||||||
expect(store.listCollections()).toEqual([]);
|
expect(store.listCollections()).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("loads an empty store when the list of what the refresh could not decrypt is damaged", async () => {
|
||||||
|
// A backup reads that list on every run, so a damaged one that loaded
|
||||||
|
// would fail every backup until the cache was deleted. A string is
|
||||||
|
// damaged too, though JavaScript can loop over its characters.
|
||||||
|
mkdirSync(join(dir, "cache"), { recursive: true });
|
||||||
|
for (const undecryptable of [{}, "not a list", [1]]) {
|
||||||
|
writeFileSync(
|
||||||
|
path,
|
||||||
|
JSON.stringify({
|
||||||
|
schemaVersion: METADATA_SCHEMA_VERSION,
|
||||||
|
userID: 42,
|
||||||
|
collectionsSinceTime: 0,
|
||||||
|
collections: [],
|
||||||
|
files: [],
|
||||||
|
undecryptable,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const store = await MetadataStore.load(path);
|
||||||
|
expect(store.userID).toBe(0);
|
||||||
|
expect(store.listUndecryptable()).toEqual([]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("creates the directory 0700 and the file 0600", async () => {
|
it("creates the directory 0700 and the file 0600", async () => {
|
||||||
const store = await MetadataStore.load(path);
|
const store = await MetadataStore.load(path);
|
||||||
store.putCollection(sampleCollection());
|
store.putCollection(sampleCollection());
|
||||||
|
|||||||
Reference in New Issue
Block a user