mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-05-20 14:21:35 +00:00
chore(format): no intentional behaviour change - runs pretty
This commit is contained in:
@@ -8,9 +8,8 @@ import { TestPaneView, VIEW_TYPE_TEST } from "./devUtil/TestPaneView.ts";
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
export class ModuleDev extends AbstractObsidianModule implements IObsidianModule {
|
||||
|
||||
$everyOnloadStart(): Promise<boolean> {
|
||||
__onMissingTranslation(() => { });
|
||||
__onMissingTranslation(() => {});
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
$everyOnloadAfterLoadSettings(): Promise<boolean> {
|
||||
@@ -18,70 +17,80 @@ export class ModuleDev extends AbstractObsidianModule implements IObsidianModule
|
||||
// eslint-disable-next-line no-unused-labels
|
||||
__onMissingTranslation((key) => {
|
||||
const now = new Date();
|
||||
const filename = `missing-translation-`
|
||||
const filename = `missing-translation-`;
|
||||
const time = now.toISOString().split("T")[0];
|
||||
const outFile = `${filename}${time}.jsonl`;
|
||||
const piece = JSON.stringify(
|
||||
{
|
||||
[key]: {}
|
||||
}
|
||||
)
|
||||
const piece = JSON.stringify({
|
||||
[key]: {},
|
||||
});
|
||||
const writePiece = piece.substring(1, piece.length - 1) + ",";
|
||||
fireAndForget(async () => {
|
||||
try {
|
||||
await this.core.storageAccess.ensureDir(this.app.vault.configDir + "/ls-debug/");
|
||||
await this.core.storageAccess.appendHiddenFile(this.app.vault.configDir + "/ls-debug/" + outFile, writePiece + "\n")
|
||||
await this.core.storageAccess.appendHiddenFile(
|
||||
this.app.vault.configDir + "/ls-debug/" + outFile,
|
||||
writePiece + "\n"
|
||||
);
|
||||
} catch (ex) {
|
||||
this._log(`Could not write ${outFile}`, LOG_LEVEL_VERBOSE);
|
||||
this._log(`Missing translation: ${writePiece}`, LOG_LEVEL_VERBOSE);
|
||||
this._log(ex, LOG_LEVEL_VERBOSE);
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
type STUB = {
|
||||
toc: Set<string>,
|
||||
stub: { [key: string]: { [key: string]: Map<string, Record<string, string>> } }
|
||||
toc: Set<string>;
|
||||
stub: { [key: string]: { [key: string]: Map<string, Record<string, string>> } };
|
||||
};
|
||||
eventHub.onEvent("document-stub-created", (detail: STUB) => {
|
||||
fireAndForget(async () => {
|
||||
const stub = detail.stub;
|
||||
const toc = detail.toc;
|
||||
|
||||
const stubDocX =
|
||||
Object.entries(stub).map(([key, value]) => {
|
||||
return [`## ${key}`, Object.entries(value).
|
||||
map(([key2, value2]) => {
|
||||
return [`### ${key2}`,
|
||||
([...(value2.entries())].map(([key3, value3]) => {
|
||||
// return `#### ${key3}` + "\n" + JSON.stringify(value3);
|
||||
const isObsolete = value3["is_obsolete"] ? " (obsolete)" : "";
|
||||
const desc = value3["desc"] ?? "";
|
||||
const key = value3["key"] ? "Setting key: " + value3["key"] + "\n" : "";
|
||||
return `#### ${key3}${isObsolete}\n${key}${desc}\n`
|
||||
}))].flat()
|
||||
}).flat()].flat()
|
||||
}).flat();
|
||||
const stubDocMD = `
|
||||
const stubDocX = Object.entries(stub)
|
||||
.map(([key, value]) => {
|
||||
return [
|
||||
`## ${key}`,
|
||||
Object.entries(value)
|
||||
.map(([key2, value2]) => {
|
||||
return [
|
||||
`### ${key2}`,
|
||||
[...value2.entries()].map(([key3, value3]) => {
|
||||
// return `#### ${key3}` + "\n" + JSON.stringify(value3);
|
||||
const isObsolete = value3["is_obsolete"] ? " (obsolete)" : "";
|
||||
const desc = value3["desc"] ?? "";
|
||||
const key = value3["key"] ? "Setting key: " + value3["key"] + "\n" : "";
|
||||
return `#### ${key3}${isObsolete}\n${key}${desc}\n`;
|
||||
}),
|
||||
].flat();
|
||||
})
|
||||
.flat(),
|
||||
].flat();
|
||||
})
|
||||
.flat();
|
||||
const stubDocMD =
|
||||
`
|
||||
| Icon | Description |
|
||||
| :---: | ----------------------------------------------------------------- |
|
||||
` +
|
||||
[...toc.values()].map(e => `${e}`).join("\n") + "\n\n" +
|
||||
[...toc.values()].map((e) => `${e}`).join("\n") +
|
||||
"\n\n" +
|
||||
stubDocX.join("\n");
|
||||
await this.core.storageAccess.writeHiddenFileAuto(this.app.vault.configDir + "/ls-debug/stub-doc.md", stubDocMD);
|
||||
})
|
||||
await this.core.storageAccess.writeHiddenFileAuto(
|
||||
this.app.vault.configDir + "/ls-debug/stub-doc.md",
|
||||
stubDocMD
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
enableTestFunction(this.plugin);
|
||||
this.registerView(
|
||||
VIEW_TYPE_TEST,
|
||||
(leaf) => new TestPaneView(leaf, this.plugin, this)
|
||||
);
|
||||
this.registerView(VIEW_TYPE_TEST, (leaf) => new TestPaneView(leaf, this.plugin, this));
|
||||
this.addCommand({
|
||||
id: "view-test",
|
||||
name: "Open Test dialogue",
|
||||
callback: () => {
|
||||
void this.core.$$showView(VIEW_TYPE_TEST);
|
||||
}
|
||||
},
|
||||
});
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
@@ -111,4 +120,4 @@ export class ModuleDev extends AbstractObsidianModule implements IObsidianModule
|
||||
// this.addTestResult("Test of test3", true);
|
||||
return this.testDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,10 @@ import { shareRunningResult } from "octagonal-wheels/concurrency/lock";
|
||||
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule";
|
||||
|
||||
export class ModuleIntegratedTest extends AbstractObsidianModule implements IObsidianModule {
|
||||
|
||||
async waitFor(proc: () => Promise<boolean>, timeout = 10000): Promise<boolean> {
|
||||
await delay(100);
|
||||
const start = Date.now();
|
||||
while (!await proc()) {
|
||||
while (!(await proc())) {
|
||||
if (timeout > 0) {
|
||||
if (Date.now() - start > timeout) {
|
||||
this._log(`Timeout`);
|
||||
@@ -40,25 +39,27 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
}
|
||||
}
|
||||
async assert(proc: () => Promise<boolean>): Promise<boolean> {
|
||||
if (!await proc()) {
|
||||
if (!(await proc())) {
|
||||
this._log(`Assertion failed`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async _orDie(key: string, proc: () => Promise<boolean>): Promise<true> | never {
|
||||
if (!await this._test(key, proc)) {
|
||||
if (!(await this._test(key, proc))) {
|
||||
throw new Error(`${key}`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
tryReplicate() {
|
||||
if (!this.settings.liveSync) {
|
||||
return shareRunningResult("replicate-test", async () => { await this.core.$$replicate() });
|
||||
return shareRunningResult("replicate-test", async () => {
|
||||
await this.core.$$replicate();
|
||||
});
|
||||
}
|
||||
}
|
||||
async readStorageContent(file: FilePathWithPrefix): Promise<string | undefined> {
|
||||
if (!await this.core.storageAccess.isExistsIncludeHidden(file)) {
|
||||
if (!(await this.core.storageAccess.isExistsIncludeHidden(file))) {
|
||||
return undefined;
|
||||
}
|
||||
return await this.core.storageAccess.readHiddenFileText(file);
|
||||
@@ -70,13 +71,14 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
await this.core.$anyResolveConflictByNewest(stepFile);
|
||||
await this.core.storageAccess.writeFileAuto(stepFile, stepContent);
|
||||
await this._orDie(`Wait for acknowledge ${no}`, async () => {
|
||||
if (!await this.waitWithReplicating(
|
||||
async () => {
|
||||
return await this.storageContentIsEqual(stepAckFile, stepContent)
|
||||
}, 20000)
|
||||
) return false;
|
||||
if (
|
||||
!(await this.waitWithReplicating(async () => {
|
||||
return await this.storageContentIsEqual(stepAckFile, stepContent);
|
||||
}, 20000))
|
||||
)
|
||||
return false;
|
||||
return true;
|
||||
})
|
||||
});
|
||||
return true;
|
||||
}
|
||||
async _join(no: number, title: string): Promise<boolean> {
|
||||
@@ -86,14 +88,14 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
const stepContent = `Step ${no}`;
|
||||
|
||||
await this._orDie(`Wait for step ${no} (${title})`, async () => {
|
||||
if (!await this.waitWithReplicating(
|
||||
async () => {
|
||||
return await this.storageContentIsEqual(stepFile, stepContent)
|
||||
}, 20000)
|
||||
) return false;
|
||||
if (
|
||||
!(await this.waitWithReplicating(async () => {
|
||||
return await this.storageContentIsEqual(stepFile, stepContent);
|
||||
}, 20000))
|
||||
)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
)
|
||||
});
|
||||
await this.core.$anyResolveConflictByNewest(stepAckFile);
|
||||
await this.core.storageAccess.writeFileAuto(stepAckFile, stepContent);
|
||||
await this.tryReplicate();
|
||||
@@ -105,13 +107,13 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
title,
|
||||
isGameChanger,
|
||||
proc,
|
||||
check
|
||||
check,
|
||||
}: {
|
||||
step: number,
|
||||
title: string,
|
||||
isGameChanger: boolean,
|
||||
proc: () => Promise<any>,
|
||||
check: () => Promise<boolean>,
|
||||
step: number;
|
||||
title: string;
|
||||
isGameChanger: boolean;
|
||||
proc: () => Promise<any>;
|
||||
check: () => Promise<boolean>;
|
||||
}): Promise<boolean> {
|
||||
if (isGameChanger) {
|
||||
await this._proceed(step, title);
|
||||
@@ -121,9 +123,7 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
this._log(`Error: ${e}`);
|
||||
return false;
|
||||
}
|
||||
return await this._orDie(`Step ${step} - ${title}`,
|
||||
async () => await this.waitWithReplicating(check)
|
||||
);
|
||||
return await this._orDie(`Step ${step} - ${title}`, async () => await this.waitWithReplicating(check));
|
||||
} else {
|
||||
return await this._join(step, title);
|
||||
}
|
||||
@@ -135,14 +135,21 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
// async testReceiver(testMain: (testFileName: FilePathWithPrefix) => Promise<boolean>): Promise<boolean> {
|
||||
|
||||
// }
|
||||
async nonLiveTestRunner(isLeader: boolean, testMain: (testFileName: FilePathWithPrefix, isLeader: boolean) => Promise<boolean>): Promise<boolean> {
|
||||
async nonLiveTestRunner(
|
||||
isLeader: boolean,
|
||||
testMain: (testFileName: FilePathWithPrefix, isLeader: boolean) => Promise<boolean>
|
||||
): Promise<boolean> {
|
||||
const storage = this.core.storageAccess;
|
||||
// const database = this.core.databaseFileAccess;
|
||||
// const _orDie = this._orDie.bind(this);
|
||||
const testCommandFile = "IT.md" as FilePathWithPrefix;
|
||||
const textCommandResponseFile = "ITx.md" as FilePathWithPrefix;
|
||||
let testFileName: FilePathWithPrefix;
|
||||
this.addTestResult("-------Starting ... ", true, `Test as ${isLeader ? "Leader" : "Receiver"} command file ${testCommandFile}`);
|
||||
this.addTestResult(
|
||||
"-------Starting ... ",
|
||||
true,
|
||||
`Test as ${isLeader ? "Leader" : "Receiver"} command file ${testCommandFile}`
|
||||
);
|
||||
if (isLeader) {
|
||||
await this._proceed(0, "start");
|
||||
}
|
||||
@@ -154,14 +161,14 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => await storage.removeHidden(testCommandFile),
|
||||
check: async () => !(await storage.isExistsIncludeHidden(testCommandFile)),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 1,
|
||||
title: "Make sure that command File Not Exists On Receiver",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => await storage.removeHidden(textCommandResponseFile),
|
||||
check: async () => !(await storage.isExistsIncludeHidden(textCommandResponseFile)),
|
||||
})
|
||||
});
|
||||
|
||||
await this.performStep({
|
||||
step: 2,
|
||||
@@ -173,14 +180,14 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
await storage.writeFileAuto(testCommandFile, testFileName);
|
||||
},
|
||||
check: () => Promise.resolve(true),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 3,
|
||||
title: "Wait for the command file to be arrived",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await storage.isExistsIncludeHidden(testCommandFile),
|
||||
})
|
||||
});
|
||||
|
||||
await this.performStep({
|
||||
step: 4,
|
||||
@@ -190,34 +197,31 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
await storage.writeHiddenFileAuto(textCommandResponseFile, "!");
|
||||
},
|
||||
check: () => Promise.resolve(true),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 5,
|
||||
title: "Wait for the response file to be arrived",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await storage.isExistsIncludeHidden(textCommandResponseFile),
|
||||
})
|
||||
});
|
||||
|
||||
await this.performStep({
|
||||
step: 6,
|
||||
title: "Proceed to begin the test",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => {
|
||||
|
||||
},
|
||||
proc: async () => {},
|
||||
check: () => Promise.resolve(true),
|
||||
});
|
||||
await this.performStep({
|
||||
step: 6,
|
||||
title: "Begin the test",
|
||||
isGameChanger: !false,
|
||||
proc: async () => {
|
||||
},
|
||||
proc: async () => {},
|
||||
check: () => {
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
})
|
||||
});
|
||||
// await this.step(0, isLeader, true);
|
||||
try {
|
||||
this.addTestResult("** Main------", true, ``);
|
||||
@@ -234,15 +238,18 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
}
|
||||
|
||||
return true;
|
||||
// Make sure the
|
||||
// Make sure the
|
||||
}
|
||||
|
||||
|
||||
async testBasic(filename: FilePathWithPrefix, isLeader: boolean): Promise<boolean> {
|
||||
const storage = this.core.storageAccess;
|
||||
const database = this.core.databaseFileAccess;
|
||||
|
||||
await this.addTestResult(`---**Starting Basic Test**---`, true, `Test as ${isLeader ? "Leader" : "Receiver"} command file ${filename}`);
|
||||
await this.addTestResult(
|
||||
`---**Starting Basic Test**---`,
|
||||
true,
|
||||
`Test as ${isLeader ? "Leader" : "Receiver"} command file ${filename}`
|
||||
);
|
||||
// if (isLeader) {
|
||||
// await this._proceed(0);
|
||||
// }
|
||||
@@ -252,10 +259,9 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
step: 0,
|
||||
title: "Make sure that file is not exist",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => !(await storage.isExists(filename)),
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
await this.performStep({
|
||||
step: 1,
|
||||
@@ -263,47 +269,47 @@ export class ModuleIntegratedTest extends AbstractObsidianModule implements IObs
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => await storage.writeFileAuto(filename, "Hello World"),
|
||||
check: async () => await storage.isExists(filename),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 2,
|
||||
title: "Make sure the file is arrived",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await storage.isExists(filename),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 3,
|
||||
title: "Update to Hello World 2",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => await storage.writeFileAuto(filename, "Hello World 2"),
|
||||
check: async () => await this.storageContentIsEqual(filename, "Hello World 2"),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 4,
|
||||
title: "Make sure the modified file is arrived",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await this.storageContentIsEqual(filename, "Hello World 2"),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 5,
|
||||
title: "Update to Hello World 3",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => await storage.writeFileAuto(filename, "Hello World 3"),
|
||||
check: async () => await this.storageContentIsEqual(filename, "Hello World 3"),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 6,
|
||||
title: "Make sure the modified file is arrived",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await this.storageContentIsEqual(filename, "Hello World 3"),
|
||||
})
|
||||
});
|
||||
|
||||
const multiLineContent = `Line1:A
|
||||
Line2:B
|
||||
Line3:C
|
||||
Line4:D`
|
||||
Line4:D`;
|
||||
|
||||
await this.performStep({
|
||||
step: 7,
|
||||
@@ -311,38 +317,35 @@ Line4:D`
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => await storage.writeFileAuto(filename, multiLineContent),
|
||||
check: async () => await this.storageContentIsEqual(filename, multiLineContent),
|
||||
})
|
||||
});
|
||||
|
||||
await this.performStep({
|
||||
step: 8,
|
||||
title: "Make sure the modified file is arrived",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await this.storageContentIsEqual(filename, multiLineContent),
|
||||
})
|
||||
});
|
||||
|
||||
// While LiveSync, possibly cannot cause the conflict.
|
||||
if (!this.settings.liveSync) {
|
||||
|
||||
|
||||
|
||||
// Step 9 Make Conflict But Resolvable
|
||||
const multiLineContentL = `Line1:A
|
||||
Line2:B
|
||||
Line3:C!
|
||||
Line4:D`
|
||||
Line4:D`;
|
||||
const multiLineContentC = `Line1:A
|
||||
Line2:bbbbb
|
||||
Line3:C
|
||||
Line4:D`
|
||||
Line4:D`;
|
||||
|
||||
await this.performStep({
|
||||
step: 9,
|
||||
title: "Progress to be conflicted",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: () => Promise.resolve(true),
|
||||
})
|
||||
});
|
||||
|
||||
await storage.writeFileAuto(filename, isLeader ? multiLineContentL : multiLineContentC);
|
||||
|
||||
@@ -350,62 +353,62 @@ Line4:D`
|
||||
step: 10,
|
||||
title: "Update As Conflicted",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: () => Promise.resolve(true),
|
||||
})
|
||||
});
|
||||
|
||||
await this.performStep({
|
||||
step: 10,
|
||||
title: "Make sure Automatically resolved",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => (await database.getConflictedRevs(filename)).length === 0,
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 11,
|
||||
title: "Make sure Automatically resolved",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => (await database.getConflictedRevs(filename)).length === 0,
|
||||
})
|
||||
|
||||
|
||||
});
|
||||
|
||||
const sensiblyMergedContent = `Line1:A
|
||||
Line2:bbbbb
|
||||
Line3:C!
|
||||
Line4:D`
|
||||
Line4:D`;
|
||||
|
||||
await this.performStep({
|
||||
step: 12,
|
||||
title: "Make sure Sensibly Merged on Leader",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await this.storageContentIsEqual(filename, sensiblyMergedContent),
|
||||
})
|
||||
});
|
||||
await this.performStep({
|
||||
step: 13,
|
||||
title: "Make sure Sensibly Merged on Receiver",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
proc: async () => {},
|
||||
check: async () => await this.storageContentIsEqual(filename, sensiblyMergedContent),
|
||||
})
|
||||
});
|
||||
}
|
||||
await this.performStep({
|
||||
step: 14,
|
||||
title: "Delete File",
|
||||
isGameChanger: isLeader,
|
||||
proc: async () => { await storage.removeHidden(filename) },
|
||||
check: async () => !await storage.isExists(filename),
|
||||
})
|
||||
proc: async () => {
|
||||
await storage.removeHidden(filename);
|
||||
},
|
||||
check: async () => !(await storage.isExists(filename)),
|
||||
});
|
||||
|
||||
await this.performStep({
|
||||
step: 15,
|
||||
title: "Make sure File is deleted",
|
||||
isGameChanger: !isLeader,
|
||||
proc: async () => { },
|
||||
check: async () => !await storage.isExists(filename),
|
||||
})
|
||||
proc: async () => {},
|
||||
check: async () => !(await storage.isExists(filename)),
|
||||
});
|
||||
this._log(`The Basic Test has been completed`, LOG_LEVEL_NOTICE);
|
||||
return true;
|
||||
}
|
||||
@@ -429,13 +432,12 @@ Line4:D`
|
||||
this._log(`Starting Test`);
|
||||
await this.testBasicEvent(isLeader);
|
||||
if (this.settings.remoteType == REMOTE_MINIO) await this.testBasicLive(isLeader);
|
||||
|
||||
} catch (e) {
|
||||
this._log(e)
|
||||
this._log(e);
|
||||
this._log(`Error: ${e}`);
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@ declare global {
|
||||
}
|
||||
|
||||
export class ModuleReplicateTest extends AbstractObsidianModule implements IObsidianModule {
|
||||
|
||||
|
||||
testRootPath = "_test/";
|
||||
testInfoPath = "_testinfo/";
|
||||
|
||||
@@ -24,7 +22,6 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
return this.core.$$getVaultName().indexOf("dev") >= 0 && this.core.$$vaultName().indexOf("recv") < 0;
|
||||
}
|
||||
|
||||
|
||||
get nameByKind() {
|
||||
if (!this.isLeader) {
|
||||
return "RECV";
|
||||
@@ -51,7 +48,6 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async dumpList() {
|
||||
if (this.settings.syncInternalFiles) {
|
||||
this._log("Write file list (Include Hidden)");
|
||||
@@ -75,39 +71,38 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
void this._dumpFileList("files.md").finally(() => {
|
||||
void this.refreshSyncStatus();
|
||||
});
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: "dump-file-structure-ih",
|
||||
name: "Dump Structure (Include Hidden)",
|
||||
callback: () => {
|
||||
const d = "files.md";
|
||||
void this._dumpFileListIncludeHidden(d);
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: "dump-file-structure-auto",
|
||||
name: "Dump Structure",
|
||||
callback: () => {
|
||||
void this.dumpList();
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: "dump-file-test",
|
||||
name: `Perform Test (Dev) ${this.isLeader ? "(Leader)" : "(Recv)"}`,
|
||||
callback: () => {
|
||||
void this.performTestManually();
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: "watch-sync-result",
|
||||
name: `Watch sync result is matched between devices`,
|
||||
callback: () => {
|
||||
this.watchIsSynchronised = !this.watchIsSynchronised;
|
||||
void this.refreshSyncStatus();
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
this.app.vault.on("modify", async (file) => {
|
||||
if (file.path.startsWith(this.testInfoPath)) {
|
||||
await this.refreshSyncStatus();
|
||||
@@ -117,7 +112,7 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
return true;
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
this.statusBarSyncStatus = this.plugin.addStatusBarItem();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
@@ -164,12 +159,11 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async _dumpFileList(outFile?: string) {
|
||||
const files = this.core.storageAccess.getFiles();
|
||||
const out = [] as any[];
|
||||
for (const file of files) {
|
||||
if (!await this.core.$$isTargetFile(file.path)) {
|
||||
if (!(await this.core.$$isTargetFile(file.path))) {
|
||||
continue;
|
||||
}
|
||||
if (file.path.startsWith(this.testInfoPath)) continue;
|
||||
@@ -183,8 +177,8 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
name: file.name,
|
||||
size: stat.size,
|
||||
mtime: stat.mtime,
|
||||
hash: hashStr
|
||||
}
|
||||
hash: hashStr,
|
||||
};
|
||||
// const fileLine = `-${file.path}:${stat.size}:${stat.mtime}:${hashStr}`;
|
||||
out.push(item);
|
||||
}
|
||||
@@ -203,7 +197,9 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
async _dumpFileListIncludeHidden(outFile?: string) {
|
||||
const ignorePatterns = this.settings.syncInternalFilesIgnorePatterns
|
||||
.replace(/\n| /g, "")
|
||||
.split(",").filter(e => e).map(e => new RegExp(e, "i"));
|
||||
.split(",")
|
||||
.filter((e) => e)
|
||||
.map((e) => new RegExp(e, "i"));
|
||||
const out = [] as any[];
|
||||
const files = await this.core.storageAccess.getFilesIncludeHidden("", undefined, ignorePatterns);
|
||||
console.dir(files);
|
||||
@@ -222,8 +218,8 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
name: file.split("/").pop(),
|
||||
size: stat.size,
|
||||
mtime: stat.mtime,
|
||||
hash: hashStr
|
||||
}
|
||||
hash: hashStr,
|
||||
};
|
||||
// const fileLine = `-${file.path}:${stat.size}:${stat.mtime}:${hashStr}`;
|
||||
out.push(item);
|
||||
}
|
||||
@@ -263,27 +259,27 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
"docs/tech_info.md",
|
||||
"docs/terms.md",
|
||||
"docs/troubleshooting.md",
|
||||
'images/1.png',
|
||||
'images/2.png',
|
||||
'images/corrupted_data.png',
|
||||
'images/hatch.png',
|
||||
'images/lock_pattern1.png',
|
||||
'images/lock_pattern2.png',
|
||||
'images/quick_setup_1.png',
|
||||
'images/quick_setup_2.png',
|
||||
'images/quick_setup_3.png',
|
||||
'images/quick_setup_3b.png',
|
||||
'images/quick_setup_4.png',
|
||||
'images/quick_setup_5.png',
|
||||
'images/quick_setup_6.png',
|
||||
'images/quick_setup_7.png',
|
||||
'images/quick_setup_8.png',
|
||||
'images/quick_setup_9_1.png',
|
||||
'images/quick_setup_9_2.png',
|
||||
'images/quick_setup_10.png',
|
||||
'images/remote_db_setting.png',
|
||||
'images/write_logs_into_the_file.png',
|
||||
]
|
||||
"images/1.png",
|
||||
"images/2.png",
|
||||
"images/corrupted_data.png",
|
||||
"images/hatch.png",
|
||||
"images/lock_pattern1.png",
|
||||
"images/lock_pattern2.png",
|
||||
"images/quick_setup_1.png",
|
||||
"images/quick_setup_2.png",
|
||||
"images/quick_setup_3.png",
|
||||
"images/quick_setup_3b.png",
|
||||
"images/quick_setup_4.png",
|
||||
"images/quick_setup_5.png",
|
||||
"images/quick_setup_6.png",
|
||||
"images/quick_setup_7.png",
|
||||
"images/quick_setup_8.png",
|
||||
"images/quick_setup_9_1.png",
|
||||
"images/quick_setup_9_2.png",
|
||||
"images/quick_setup_10.png",
|
||||
"images/remote_db_setting.png",
|
||||
"images/write_logs_into_the_file.png",
|
||||
];
|
||||
for (const file of files) {
|
||||
const remote = remoteTopDir + file;
|
||||
const local = this.testRootPath + file;
|
||||
@@ -303,7 +299,7 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
async waitFor(proc: () => Promise<boolean>, timeout = 10000): Promise<boolean> {
|
||||
await delay(100);
|
||||
const start = Date.now();
|
||||
while (!await proc()) {
|
||||
while (!(await proc())) {
|
||||
if (timeout > 0) {
|
||||
if (Date.now() - start > timeout) {
|
||||
this._log(`Timeout`);
|
||||
@@ -316,7 +312,6 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
}
|
||||
|
||||
async testConflictedManually1() {
|
||||
|
||||
await this.core.$$replicate();
|
||||
|
||||
const commonFile = `Resolve!
|
||||
@@ -328,18 +323,20 @@ export class ModuleReplicateTest extends AbstractObsidianModule implements IObsi
|
||||
|
||||
await this.core.$$replicate();
|
||||
await this.core.$$replicate();
|
||||
if (await this.core.confirm.askYesNoDialog("Ready to begin the test conflict Manually 1?", { timeout: 30, defaultOption: "Yes" }) == "no") {
|
||||
if (
|
||||
(await this.core.confirm.askYesNoDialog("Ready to begin the test conflict Manually 1?", {
|
||||
timeout: 30,
|
||||
defaultOption: "Yes",
|
||||
})) == "no"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const fileA = `Resolve to KEEP THIS
|
||||
Willy Wonka, Willy Wonka, the amazing chocolatier!!`
|
||||
Willy Wonka, Willy Wonka, the amazing chocolatier!!`;
|
||||
|
||||
const fileB = `Resolve to DISCARD THIS
|
||||
Charlie Bucket, Charlie Bucket, the amazing chocolatier!!`
|
||||
|
||||
|
||||
Charlie Bucket, Charlie Bucket, the amazing chocolatier!!`;
|
||||
|
||||
if (this.isLeader) {
|
||||
await this.core.storageAccess.writeHiddenFileAuto(this.testRootPath + "wonka.md", fileA);
|
||||
@@ -347,25 +344,37 @@ Charlie Bucket, Charlie Bucket, the amazing chocolatier!!`
|
||||
await this.core.storageAccess.writeHiddenFileAuto(this.testRootPath + "wonka.md", fileB);
|
||||
}
|
||||
|
||||
if (await this.core.confirm.askYesNoDialog("Ready to check the result of Manually 1?", { timeout: 30, defaultOption: "Yes" }) == "no") {
|
||||
if (
|
||||
(await this.core.confirm.askYesNoDialog("Ready to check the result of Manually 1?", {
|
||||
timeout: 30,
|
||||
defaultOption: "Yes",
|
||||
})) == "no"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
await this.core.$$replicate();
|
||||
await this.core.$$replicate();
|
||||
|
||||
|
||||
if (!await this.waitFor(async () => {
|
||||
await this.core.$$replicate();
|
||||
return await this.__assertStorageContent(this.testRootPath + "wonka.md" as FilePath, fileA, false, true) == true;
|
||||
}, 30000)) {
|
||||
return await this.__assertStorageContent(this.testRootPath + "wonka.md" as FilePath, fileA, false, true);
|
||||
if (
|
||||
!(await this.waitFor(async () => {
|
||||
await this.core.$$replicate();
|
||||
return (
|
||||
(await this.__assertStorageContent(
|
||||
(this.testRootPath + "wonka.md") as FilePath,
|
||||
fileA,
|
||||
false,
|
||||
true
|
||||
)) == true
|
||||
);
|
||||
}, 30000))
|
||||
) {
|
||||
return await this.__assertStorageContent((this.testRootPath + "wonka.md") as FilePath, fileA, false, true);
|
||||
}
|
||||
return true;
|
||||
// We have to check the result
|
||||
}
|
||||
|
||||
async testConflictedManually2() {
|
||||
|
||||
await this.core.$$replicate();
|
||||
|
||||
const commonFile = `Resolve To concatenate
|
||||
@@ -377,56 +386,82 @@ ABCDEFG`;
|
||||
|
||||
await this.core.$$replicate();
|
||||
await this.core.$$replicate();
|
||||
if (await this.core.confirm.askYesNoDialog("Ready to begin the test conflict Manually 2?", { timeout: 30, defaultOption: "Yes" }) == "no") {
|
||||
if (
|
||||
(await this.core.confirm.askYesNoDialog("Ready to begin the test conflict Manually 2?", {
|
||||
timeout: 30,
|
||||
defaultOption: "Yes",
|
||||
})) == "no"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fileA = `Resolve to Concatenate
|
||||
ABCDEFGHIJKLMNOPQRSTYZ`
|
||||
ABCDEFGHIJKLMNOPQRSTYZ`;
|
||||
|
||||
const fileB = `Resolve to Concatenate
|
||||
AJKLMNOPQRSTUVWXYZ`
|
||||
AJKLMNOPQRSTUVWXYZ`;
|
||||
|
||||
const concatenated = `Resolve to Concatenate
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXYZ`;
|
||||
if (this.isLeader) {
|
||||
await this.core.storageAccess.writeHiddenFileAuto(this.testRootPath + "concat.md", fileA);
|
||||
} else {
|
||||
await this.core.storageAccess.writeHiddenFileAuto(this.testRootPath + "concat.md", fileB);
|
||||
}
|
||||
if (await this.core.confirm.askYesNoDialog("Ready to test conflict Manually 2?", { timeout: 30, defaultOption: "Yes" }) == "no") {
|
||||
if (
|
||||
(await this.core.confirm.askYesNoDialog("Ready to test conflict Manually 2?", {
|
||||
timeout: 30,
|
||||
defaultOption: "Yes",
|
||||
})) == "no"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
await this.core.$$replicate();
|
||||
await this.core.$$replicate();
|
||||
|
||||
|
||||
if (!await this.waitFor(async () => {
|
||||
await this.core.$$replicate();
|
||||
return await this.__assertStorageContent(this.testRootPath + "concat.md" as FilePath, concatenated, false, true) == true;
|
||||
}, 30000)) {
|
||||
return await this.__assertStorageContent(this.testRootPath + "concat.md" as FilePath, concatenated, false, true);
|
||||
if (
|
||||
!(await this.waitFor(async () => {
|
||||
await this.core.$$replicate();
|
||||
return (
|
||||
(await this.__assertStorageContent(
|
||||
(this.testRootPath + "concat.md") as FilePath,
|
||||
concatenated,
|
||||
false,
|
||||
true
|
||||
)) == true
|
||||
);
|
||||
}, 30000))
|
||||
) {
|
||||
return await this.__assertStorageContent(
|
||||
(this.testRootPath + "concat.md") as FilePath,
|
||||
concatenated,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
async testConflictAutomatic() {
|
||||
|
||||
if (this.isLeader) {
|
||||
const baseDoc = `Tasks!
|
||||
- [ ] Task 1
|
||||
- [ ] Task 2
|
||||
- [ ] Task 3
|
||||
- [ ] Task 4
|
||||
`
|
||||
`;
|
||||
await this.core.storageAccess.writeHiddenFileAuto(this.testRootPath + "task.md", baseDoc);
|
||||
}
|
||||
await delay(100)
|
||||
await delay(100);
|
||||
await this.core.$$replicate();
|
||||
await this.core.$$replicate();
|
||||
|
||||
if (await this.core.confirm.askYesNoDialog("Ready to test conflict?", { timeout: 30, defaultOption: "Yes" }) == "no") {
|
||||
if (
|
||||
(await this.core.confirm.askYesNoDialog("Ready to test conflict?", {
|
||||
timeout: 30,
|
||||
defaultOption: "Yes",
|
||||
})) == "no"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const mod1Doc = `Tasks!
|
||||
@@ -434,14 +469,14 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
- [v] Task 2
|
||||
- [ ] Task 3
|
||||
- [ ] Task 4
|
||||
`
|
||||
`;
|
||||
|
||||
const mod2Doc = `Tasks!
|
||||
- [ ] Task 1
|
||||
- [ ] Task 2
|
||||
- [v] Task 3
|
||||
- [ ] Task 4
|
||||
`
|
||||
`;
|
||||
if (this.isLeader) {
|
||||
await this.core.storageAccess.writeHiddenFileAuto(this.testRootPath + "task.md", mod1Doc);
|
||||
} else {
|
||||
@@ -451,7 +486,10 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
await this.core.$$replicate();
|
||||
await this.core.$$replicate();
|
||||
await delay(1000);
|
||||
if (await this.core.confirm.askYesNoDialog("Ready to check result?", { timeout: 30, defaultOption: "Yes" }) == "no") {
|
||||
if (
|
||||
(await this.core.confirm.askYesNoDialog("Ready to check result?", { timeout: 30, defaultOption: "Yes" })) ==
|
||||
"no"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
await this.core.$$replicate();
|
||||
@@ -461,8 +499,8 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
- [v] Task 2
|
||||
- [v] Task 3
|
||||
- [ ] Task 4
|
||||
`
|
||||
return this.__assertStorageContent(this.testRootPath + "task.md" as FilePath, mergedDoc, false, true);
|
||||
`;
|
||||
return this.__assertStorageContent((this.testRootPath + "task.md") as FilePath, mergedDoc, false, true);
|
||||
}
|
||||
|
||||
async checkConflictResolution() {
|
||||
@@ -471,24 +509,27 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
await this.core.rebuilder.resolveAllConflictedFilesByNewerOnes();
|
||||
await this.core.$$replicate();
|
||||
await delay(1000);
|
||||
if (!await this.testConflictAutomatic()) {
|
||||
if (!(await this.testConflictAutomatic())) {
|
||||
this._log("Conflict resolution (Auto) failed", LOG_LEVEL_NOTICE);
|
||||
return false;
|
||||
}
|
||||
if (!await this.testConflictedManually1()) {
|
||||
if (!(await this.testConflictedManually1())) {
|
||||
this._log("Conflict resolution (Manual1) failed", LOG_LEVEL_NOTICE);
|
||||
return false;
|
||||
}
|
||||
if (!await this.testConflictedManually2()) {
|
||||
if (!(await this.testConflictedManually2())) {
|
||||
this._log("Conflict resolution (Manual2) failed", LOG_LEVEL_NOTICE);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
async __assertStorageContent(fileName: FilePath, content: string, inverted = false, showResult = false): Promise<boolean | string> {
|
||||
async __assertStorageContent(
|
||||
fileName: FilePath,
|
||||
content: string,
|
||||
inverted = false,
|
||||
showResult = false
|
||||
): Promise<boolean | string> {
|
||||
try {
|
||||
const fileContent = await this.core.storageAccess.readHiddenFileText(fileName);
|
||||
let result = fileContent === content;
|
||||
@@ -531,4 +572,4 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
await this._test("Conflict resolution", async () => await this.checkConflictResolution());
|
||||
return this.testDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import {
|
||||
ItemView,
|
||||
WorkspaceLeaf
|
||||
} from "obsidian";
|
||||
import TestPaneComponent from "./TestPane.svelte"
|
||||
import type ObsidianLiveSyncPlugin from "../../../main.ts"
|
||||
import { ItemView, WorkspaceLeaf } from "obsidian";
|
||||
import TestPaneComponent from "./TestPane.svelte";
|
||||
import type ObsidianLiveSyncPlugin from "../../../main.ts";
|
||||
import type { ModuleDev } from "../ModuleDev.ts";
|
||||
export const VIEW_TYPE_TEST = "ols-pane-test";
|
||||
//Log view
|
||||
export class TestPaneView extends ItemView {
|
||||
|
||||
component?: TestPaneComponent;
|
||||
plugin: ObsidianLiveSyncPlugin;
|
||||
moduleDev: ModuleDev;
|
||||
icon = "view-log";
|
||||
title: string = "Self-hosted LiveSync Test and Results"
|
||||
title: string = "Self-hosted LiveSync Test and Results";
|
||||
navigation = true;
|
||||
|
||||
getIcon(): string {
|
||||
@@ -26,7 +22,6 @@ export class TestPaneView extends ItemView {
|
||||
this.moduleDev = moduleDev;
|
||||
}
|
||||
|
||||
|
||||
getViewType() {
|
||||
return VIEW_TYPE_TEST;
|
||||
}
|
||||
@@ -41,7 +36,7 @@ export class TestPaneView extends ItemView {
|
||||
target: this.contentEl,
|
||||
props: {
|
||||
plugin: this.plugin,
|
||||
moduleDev: this.moduleDev
|
||||
moduleDev: this.moduleDev,
|
||||
},
|
||||
});
|
||||
await Promise.resolve();
|
||||
|
||||
@@ -7,40 +7,44 @@ export function enableTestFunction(plugin_: ObsidianLiveSyncPlugin) {
|
||||
plugin = plugin_;
|
||||
}
|
||||
export function addDebugFileLog(message: any, stackLog = false) {
|
||||
fireAndForget(serialized("debug-log", async () => {
|
||||
const now = new Date();
|
||||
const filename = `debug-log`
|
||||
const time = now.toISOString().split("T")[0];
|
||||
const outFile = `${filename}${time}.jsonl`;
|
||||
// const messageContent = typeof message == "string" ? message : message instanceof Error ? `${message.name}:${message.message}` : JSON.stringify(message, null, 2);
|
||||
const timestamp = now.toLocaleString();
|
||||
const timestampEpoch = now;
|
||||
let out = { "timestamp": timestamp, epoch: timestampEpoch, } as Record<string, any>;
|
||||
if (message instanceof Error) {
|
||||
// debugger;
|
||||
// console.dir(message.stack);
|
||||
out = { ...out, message };
|
||||
} else if (stackLog) {
|
||||
if (stackLog) {
|
||||
const stackE = new Error();
|
||||
const stack = stackE.stack;
|
||||
out = { ...out, stack }
|
||||
fireAndForget(
|
||||
serialized("debug-log", async () => {
|
||||
const now = new Date();
|
||||
const filename = `debug-log`;
|
||||
const time = now.toISOString().split("T")[0];
|
||||
const outFile = `${filename}${time}.jsonl`;
|
||||
// const messageContent = typeof message == "string" ? message : message instanceof Error ? `${message.name}:${message.message}` : JSON.stringify(message, null, 2);
|
||||
const timestamp = now.toLocaleString();
|
||||
const timestampEpoch = now;
|
||||
let out = { timestamp: timestamp, epoch: timestampEpoch } as Record<string, any>;
|
||||
if (message instanceof Error) {
|
||||
// debugger;
|
||||
// console.dir(message.stack);
|
||||
out = { ...out, message };
|
||||
} else if (stackLog) {
|
||||
if (stackLog) {
|
||||
const stackE = new Error();
|
||||
const stack = stackE.stack;
|
||||
out = { ...out, stack };
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof message == "object") {
|
||||
out = { ...out, ...message, }
|
||||
} else {
|
||||
out = {
|
||||
result: message
|
||||
if (typeof message == "object") {
|
||||
out = { ...out, ...message };
|
||||
} else {
|
||||
out = {
|
||||
result: message,
|
||||
};
|
||||
}
|
||||
}
|
||||
// const out = "--" + timestamp + "--\n" + messageContent + " " + (stack || "");
|
||||
// const out
|
||||
try {
|
||||
await plugin.storageAccess.appendHiddenFile(plugin.app.vault.configDir + "/ls-debug/" + outFile, JSON.stringify(out) + "\n")
|
||||
} catch {
|
||||
|
||||
//NO OP
|
||||
}
|
||||
}));
|
||||
}
|
||||
// const out = "--" + timestamp + "--\n" + messageContent + " " + (stack || "");
|
||||
// const out
|
||||
try {
|
||||
await plugin.storageAccess.appendHiddenFile(
|
||||
plugin.app.vault.configDir + "/ls-debug/" + outFile,
|
||||
JSON.stringify(out) + "\n"
|
||||
);
|
||||
} catch {
|
||||
//NO OP
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const measures = new Map<string, MeasureResult>();
|
||||
function clearResult(name: string) {
|
||||
measures.set(name, [0, 0]);
|
||||
}
|
||||
async function measureEach(name: string, proc: () => (void | Promise<void>)) {
|
||||
async function measureEach(name: string, proc: () => void | Promise<void>) {
|
||||
const [times, spent] = measures.get(name) ?? [0, 0];
|
||||
|
||||
const start = performance.now();
|
||||
@@ -15,57 +15,76 @@ async function measureEach(name: string, proc: () => (void | Promise<void>)) {
|
||||
if (result instanceof Promise) await result;
|
||||
const end = performance.now();
|
||||
measures.set(name, [times + 1, spent + (end - start)]);
|
||||
|
||||
}
|
||||
function formatNumber(num: number) {
|
||||
return num.toLocaleString('en-US', { maximumFractionDigits: 2 });
|
||||
return num.toLocaleString("en-US", { maximumFractionDigits: 2 });
|
||||
}
|
||||
async function measure(name: string, proc: () => (void | Promise<void>), times: number = 10000, duration: number = 1000): Promise<NamedMeasureResult> {
|
||||
async function measure(
|
||||
name: string,
|
||||
proc: () => void | Promise<void>,
|
||||
times: number = 10000,
|
||||
duration: number = 1000
|
||||
): Promise<NamedMeasureResult> {
|
||||
const from = Date.now();
|
||||
let last = times;
|
||||
clearResult(name);
|
||||
do {
|
||||
await measureEach(name, proc);
|
||||
} while (last-- > 0 && (Date.now() - from) < duration)
|
||||
} while (last-- > 0 && Date.now() - from < duration);
|
||||
return [name, measures.get(name) as MeasureResult];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await, @typescript-eslint/require-await
|
||||
async function formatPerfResults(items: NamedMeasureResult[]) {
|
||||
return `| Name | Runs | Each | Total |\n| --- | --- | --- | --- | \n` + items.map(e => `| ${e[0]} | ${e[1][0]} | ${e[1][0] != 0 ? formatNumber(e[1][1] / e[1][0]) : "-"} | ${formatNumber(e[1][0])} |`).join("\n");
|
||||
|
||||
return (
|
||||
`| Name | Runs | Each | Total |\n| --- | --- | --- | --- | \n` +
|
||||
items
|
||||
.map(
|
||||
(e) =>
|
||||
`| ${e[0]} | ${e[1][0]} | ${e[1][0] != 0 ? formatNumber(e[1][1] / e[1][0]) : "-"} | ${formatNumber(e[1][0])} |`
|
||||
)
|
||||
.join("\n")
|
||||
);
|
||||
}
|
||||
export async function perf_trench(plugin: ObsidianLiveSyncPlugin) {
|
||||
clearResult("trench");
|
||||
const trench = new Trench(plugin.simpleStore);
|
||||
const result = [] as NamedMeasureResult[];
|
||||
result.push(await measure("trench-short-string", async () => {
|
||||
const p = trench.evacuate("string");
|
||||
await p();
|
||||
}));
|
||||
result.push(
|
||||
await measure("trench-short-string", async () => {
|
||||
const p = trench.evacuate("string");
|
||||
await p();
|
||||
})
|
||||
);
|
||||
{
|
||||
const testBinary = await plugin.storageAccess.readHiddenFileBinary("testdata/10kb.png");
|
||||
const uint8Array = new Uint8Array(testBinary);
|
||||
result.push(await measure("trench-binary-10kb", async () => {
|
||||
const p = trench.evacuate(uint8Array);
|
||||
await p();
|
||||
}));
|
||||
result.push(
|
||||
await measure("trench-binary-10kb", async () => {
|
||||
const p = trench.evacuate(uint8Array);
|
||||
await p();
|
||||
})
|
||||
);
|
||||
}
|
||||
{
|
||||
const testBinary = await plugin.storageAccess.readHiddenFileBinary("testdata/100kb.jpeg");
|
||||
const uint8Array = new Uint8Array(testBinary);
|
||||
result.push(await measure("trench-binary-100kb", async () => {
|
||||
const p = trench.evacuate(uint8Array);
|
||||
await p();
|
||||
}));
|
||||
result.push(
|
||||
await measure("trench-binary-100kb", async () => {
|
||||
const p = trench.evacuate(uint8Array);
|
||||
await p();
|
||||
})
|
||||
);
|
||||
}
|
||||
{
|
||||
const testBinary = await plugin.storageAccess.readHiddenFileBinary("testdata/1mb.png");
|
||||
const uint8Array = new Uint8Array(testBinary);
|
||||
result.push(await measure("trench-binary-1mb", async () => {
|
||||
const p = trench.evacuate(uint8Array);
|
||||
await p();
|
||||
}));
|
||||
result.push(
|
||||
await measure("trench-binary-1mb", async () => {
|
||||
const p = trench.evacuate(uint8Array);
|
||||
await p();
|
||||
})
|
||||
);
|
||||
}
|
||||
return formatPerfResults(result);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user