mirror of https://github.com/laurent22/joplin.git
2403 lines
33 KiB
JavaScript
2403 lines
33 KiB
JavaScript
"use strict";
|
|
|
|
const { time } = require("lib/time-utils.js");
|
|
const { Logger } = require("lib/logger.js");
|
|
const Resource = require("lib/models/Resource.js");
|
|
const { dirname } = require("lib/path-utils.js");
|
|
const { FsDriverNode } = require("./fs-driver-node.js");
|
|
const lodash = require("lodash");
|
|
const exec = require("child_process").exec;
|
|
const fs = require("fs-extra");
|
|
|
|
const baseDir = dirname(__dirname) + "/tests/fuzzing";
|
|
const syncDir = baseDir + "/sync";
|
|
const joplinAppPath = __dirname + "/main.js";
|
|
let syncDurations = [];
|
|
|
|
const fsDriver = new FsDriverNode();
|
|
Logger.fsDriver_ = fsDriver;
|
|
Resource.fsDriver_ = fsDriver;
|
|
|
|
const logger = new Logger();
|
|
logger.addTarget("console");
|
|
logger.setLevel(Logger.LEVEL_DEBUG);
|
|
|
|
process.on("unhandledRejection", (reason, p) => {
|
|
console.error("Unhandled promise rejection", p, "reason:", reason);
|
|
});
|
|
|
|
function createClient(id) {
|
|
return {
|
|
id: id,
|
|
profileDir: baseDir + "/client" + id,
|
|
};
|
|
}
|
|
|
|
async function createClients() {
|
|
let output = [];
|
|
let promises = [];
|
|
for (let clientId = 0; clientId < 2; clientId++) {
|
|
let client = createClient(clientId);
|
|
promises.push(fs.remove(client.profileDir));
|
|
promises.push(
|
|
execCommand(client, "config sync.target 2").then(() => {
|
|
return execCommand(client, "config sync.2.path " + syncDir);
|
|
})
|
|
);
|
|
output.push(client);
|
|
}
|
|
|
|
await Promise.all(promises);
|
|
|
|
return output;
|
|
}
|
|
|
|
function randomElement(array) {
|
|
if (!array.length) return null;
|
|
return array[Math.floor(Math.random() * array.length)];
|
|
}
|
|
|
|
function randomWord() {
|
|
const words = [
|
|
"belief",
|
|
"scandalous",
|
|
"flawless",
|
|
"wrestle",
|
|
"sort",
|
|
"moldy",
|
|
"carve",
|
|
"incompetent",
|
|
"cruel",
|
|
"awful",
|
|
"fang",
|
|
"holistic",
|
|
"makeshift",
|
|
"synonymous",
|
|
"questionable",
|
|
"soft",
|
|
"drop",
|
|
"boot",
|
|
"whimsical",
|
|
"stir",
|
|
"idea",
|
|
"adhesive",
|
|
"present",
|
|
"hilarious",
|
|
"unusual",
|
|
"divergent",
|
|
"probable",
|
|
"depend",
|
|
"suck",
|
|
"belong",
|
|
"advise",
|
|
"straight",
|
|
"encouraging",
|
|
"wing",
|
|
"clam",
|
|
"serve",
|
|
"fill",
|
|
"nostalgic",
|
|
"dysfunctional",
|
|
"aggressive",
|
|
"floor",
|
|
"baby",
|
|
"grease",
|
|
"sisters",
|
|
"print",
|
|
"switch",
|
|
"control",
|
|
"victorious",
|
|
"cracker",
|
|
"dream",
|
|
"wistful",
|
|
"adaptable",
|
|
"reminiscent",
|
|
"inquisitive",
|
|
"pushy",
|
|
"unaccountable",
|
|
"receive",
|
|
"guttural",
|
|
"two",
|
|
"protect",
|
|
"skin",
|
|
"unbiased",
|
|
"plastic",
|
|
"loutish",
|
|
"zip",
|
|
"used",
|
|
"divide",
|
|
"communicate",
|
|
"dear",
|
|
"muddled",
|
|
"dinosaurs",
|
|
"grip",
|
|
"trees",
|
|
"well-off",
|
|
"calendar",
|
|
"chickens",
|
|
"irate",
|
|
"deranged",
|
|
"trip",
|
|
"stream",
|
|
"white",
|
|
"poison",
|
|
"attack",
|
|
"obtain",
|
|
"theory",
|
|
"laborer",
|
|
"omniscient",
|
|
"brake",
|
|
"maniacal",
|
|
"curvy",
|
|
"smoke",
|
|
"babies",
|
|
"punch",
|
|
"hammer",
|
|
"toothbrush",
|
|
"same",
|
|
"crown",
|
|
"jagged",
|
|
"peep",
|
|
"difficult",
|
|
"reject",
|
|
"merciful",
|
|
"useless",
|
|
"doctor",
|
|
"mix",
|
|
"wicked",
|
|
"plant",
|
|
"quickest",
|
|
"roll",
|
|
"suffer",
|
|
"curly",
|
|
"brother",
|
|
"frighten",
|
|
"cold",
|
|
"tremendous",
|
|
"move",
|
|
"knot",
|
|
"lame",
|
|
"imaginary",
|
|
"capricious",
|
|
"raspy",
|
|
"aunt",
|
|
"loving",
|
|
"wink",
|
|
"wooden",
|
|
"hop",
|
|
"free",
|
|
"drab",
|
|
"fire",
|
|
"instrument",
|
|
"border",
|
|
"frame",
|
|
"silent",
|
|
"glue",
|
|
"decorate",
|
|
"distance",
|
|
"powerful",
|
|
"pig",
|
|
"admit",
|
|
"fix",
|
|
"pour",
|
|
"flesh",
|
|
"profuse",
|
|
"skinny",
|
|
"learn",
|
|
"filthy",
|
|
"dress",
|
|
"bloody",
|
|
"produce",
|
|
"innocent",
|
|
"meaty",
|
|
"pray",
|
|
"slimy",
|
|
"sun",
|
|
"kindhearted",
|
|
"dime",
|
|
"exclusive",
|
|
"boast",
|
|
"neat",
|
|
"ruthless",
|
|
"recess",
|
|
"grieving",
|
|
"daily",
|
|
"hateful",
|
|
"ignorant",
|
|
"fence",
|
|
"spring",
|
|
"slim",
|
|
"education",
|
|
"overflow",
|
|
"plastic",
|
|
"gaping",
|
|
"chew",
|
|
"detect",
|
|
"right",
|
|
"lunch",
|
|
"gainful",
|
|
"argue",
|
|
"cloistered",
|
|
"horses",
|
|
"orange",
|
|
"shame",
|
|
"bitter",
|
|
"able",
|
|
"sail",
|
|
"magical",
|
|
"exist",
|
|
"force",
|
|
"wheel",
|
|
"best",
|
|
"suit",
|
|
"spurious",
|
|
"partner",
|
|
"request",
|
|
"dog",
|
|
"gusty",
|
|
"money",
|
|
"gaze",
|
|
"lonely",
|
|
"company",
|
|
"pale",
|
|
"tempt",
|
|
"rat",
|
|
"flame",
|
|
"wobble",
|
|
"superficial",
|
|
"stop",
|
|
"protective",
|
|
"stare",
|
|
"tongue",
|
|
"heal",
|
|
"railway",
|
|
"idiotic",
|
|
"roll",
|
|
"puffy",
|
|
"turn",
|
|
"meeting",
|
|
"new",
|
|
"frightening",
|
|
"sophisticated",
|
|
"poke",
|
|
"elderly",
|
|
"room",
|
|
"stimulating",
|
|
"increase",
|
|
"moor",
|
|
"secret",
|
|
"lean",
|
|
"occur",
|
|
"country",
|
|
"damp",
|
|
"evanescent",
|
|
"alluring",
|
|
"oafish",
|
|
"join",
|
|
"thundering",
|
|
"cars",
|
|
"awesome",
|
|
"advice",
|
|
"unruly",
|
|
"ray",
|
|
"wind",
|
|
"anxious",
|
|
"fly",
|
|
"hammer",
|
|
"adventurous",
|
|
"shop",
|
|
"cook",
|
|
"trucks",
|
|
"nonchalant",
|
|
"addition",
|
|
"base",
|
|
"abashed",
|
|
"excuse",
|
|
"giants",
|
|
"dramatic",
|
|
"piquant",
|
|
"coach",
|
|
"possess",
|
|
"poor",
|
|
"finger",
|
|
"wide-eyed",
|
|
"aquatic",
|
|
"welcome",
|
|
"instruct",
|
|
"expert",
|
|
"evasive",
|
|
"hug",
|
|
"cute",
|
|
"return",
|
|
"mice",
|
|
"damage",
|
|
"turkey",
|
|
"quiet",
|
|
"bewildered",
|
|
"tidy",
|
|
"pointless",
|
|
"outrageous",
|
|
"medical",
|
|
"foolish",
|
|
"curve",
|
|
"grandiose",
|
|
"gullible",
|
|
"hapless",
|
|
"gleaming",
|
|
"third",
|
|
"grin",
|
|
"pipe",
|
|
"egg",
|
|
"act",
|
|
"physical",
|
|
"eager",
|
|
"side",
|
|
"milk",
|
|
"tearful",
|
|
"fertile",
|
|
"average",
|
|
"glamorous",
|
|
"strange",
|
|
"yak",
|
|
"terrific",
|
|
"thin",
|
|
"near",
|
|
"snails",
|
|
"flowery",
|
|
"authority",
|
|
"fish",
|
|
"curious",
|
|
"perpetual",
|
|
"healthy",
|
|
"health",
|
|
"match",
|
|
"fade",
|
|
"chemical",
|
|
"economic",
|
|
"drawer",
|
|
"avoid",
|
|
"lying",
|
|
"minister",
|
|
"lick",
|
|
"powder",
|
|
"decay",
|
|
"desire",
|
|
"furry",
|
|
"faint",
|
|
"beam",
|
|
"sordid",
|
|
"fax",
|
|
"tail",
|
|
"bawdy",
|
|
"cherry",
|
|
"letter",
|
|
"clover",
|
|
"ladybug",
|
|
"teeth",
|
|
"behavior",
|
|
"black",
|
|
"amazing",
|
|
"pink",
|
|
"waste",
|
|
"island",
|
|
"forgetful",
|
|
"needless",
|
|
"lock",
|
|
"waves",
|
|
"boundary",
|
|
"receipt",
|
|
"handy",
|
|
"religion",
|
|
"hypnotic",
|
|
"aftermath",
|
|
"explain",
|
|
"sense",
|
|
"mundane",
|
|
"rambunctious",
|
|
"second",
|
|
"preserve",
|
|
"alarm",
|
|
"dusty",
|
|
"event",
|
|
"blow",
|
|
"weigh",
|
|
"value",
|
|
"glorious",
|
|
"jail",
|
|
"sigh",
|
|
"cemetery",
|
|
"serious",
|
|
"yummy",
|
|
"cattle",
|
|
"understood",
|
|
"limit",
|
|
"alert",
|
|
"fear",
|
|
"lucky",
|
|
"tested",
|
|
"surround",
|
|
"dolls",
|
|
"pleasant",
|
|
"disillusioned",
|
|
"discover",
|
|
"tray",
|
|
"night",
|
|
"seemly",
|
|
"liquid",
|
|
"worry",
|
|
"pen",
|
|
"bent",
|
|
"gruesome",
|
|
"war",
|
|
"teeny-tiny",
|
|
"common",
|
|
"judge",
|
|
"symptomatic",
|
|
"bed",
|
|
"trot",
|
|
"unequaled",
|
|
"flowers",
|
|
"friends",
|
|
"damaged",
|
|
"peel",
|
|
"skip",
|
|
"show",
|
|
"twist",
|
|
"worthless",
|
|
"brush",
|
|
"look",
|
|
"behave",
|
|
"imperfect",
|
|
"week",
|
|
"petite",
|
|
"direction",
|
|
"soda",
|
|
"lively",
|
|
"coal",
|
|
"coil",
|
|
"release",
|
|
"berserk",
|
|
"books",
|
|
"impossible",
|
|
"replace",
|
|
"cough",
|
|
"chunky",
|
|
"torpid",
|
|
"discreet",
|
|
"material",
|
|
"bomb",
|
|
"soothe",
|
|
"crack",
|
|
"hope",
|
|
"license",
|
|
"frightened",
|
|
"breathe",
|
|
"maddening",
|
|
"calculator",
|
|
"committee",
|
|
"paltry",
|
|
"green",
|
|
"subsequent",
|
|
"arrest",
|
|
"gigantic",
|
|
"tasty",
|
|
"metal",
|
|
"willing",
|
|
"man",
|
|
"stem",
|
|
"nonstop",
|
|
"route",
|
|
"impulse",
|
|
"government",
|
|
"comfortable",
|
|
"include",
|
|
"literate",
|
|
"multiply",
|
|
"test",
|
|
"vast",
|
|
"exercise",
|
|
"addicted",
|
|
"agreeable",
|
|
"lace",
|
|
"toes",
|
|
"young",
|
|
"water",
|
|
"end",
|
|
"wash",
|
|
"glossy",
|
|
"round",
|
|
"staking",
|
|
"sink",
|
|
"open",
|
|
"spot",
|
|
"trip",
|
|
"fierce",
|
|
"robust",
|
|
"pastoral",
|
|
"drown",
|
|
"dress",
|
|
"machine",
|
|
"calculating",
|
|
"holiday",
|
|
"crabby",
|
|
"disgusting",
|
|
"plan",
|
|
"sleet",
|
|
"sleepy",
|
|
"typical",
|
|
"borrow",
|
|
"possible",
|
|
"curtain",
|
|
"airplane",
|
|
"industry",
|
|
"nut",
|
|
"rough",
|
|
"wacky",
|
|
"rock",
|
|
"enormous",
|
|
"uninterested",
|
|
"sugar",
|
|
"rake",
|
|
"consist",
|
|
"wrist",
|
|
"basket",
|
|
"chop",
|
|
"wet",
|
|
"street",
|
|
"known",
|
|
"settle",
|
|
"bless",
|
|
"cluttered",
|
|
"wild",
|
|
"expand",
|
|
"angle",
|
|
"snake",
|
|
"yawn",
|
|
"hate",
|
|
"flood",
|
|
"rabid",
|
|
"spiteful",
|
|
"anger",
|
|
"market",
|
|
"bizarre",
|
|
"force",
|
|
"majestic",
|
|
"scissors",
|
|
"beg",
|
|
"rifle",
|
|
"foregoing",
|
|
"cactus",
|
|
"funny",
|
|
"eggnog",
|
|
"wish",
|
|
"high-pitched",
|
|
"drop",
|
|
"camp",
|
|
"scarf",
|
|
"car",
|
|
"groan",
|
|
"wonderful",
|
|
"wealthy",
|
|
"cup",
|
|
"lock",
|
|
"available",
|
|
"previous",
|
|
"jam",
|
|
"political",
|
|
"vacation",
|
|
"three",
|
|
"desk",
|
|
"fry",
|
|
"aspiring",
|
|
"productive",
|
|
"clear",
|
|
"bored",
|
|
"flashy",
|
|
"plug",
|
|
"precede",
|
|
"abhorrent",
|
|
"muddle",
|
|
"flimsy",
|
|
"paste",
|
|
"need",
|
|
"reward",
|
|
"frail",
|
|
"obnoxious",
|
|
"creature",
|
|
"whip",
|
|
"unbecoming",
|
|
"lake",
|
|
"unused",
|
|
"chin",
|
|
"tour",
|
|
"zephyr",
|
|
"experience",
|
|
"building",
|
|
"scrub",
|
|
"correct",
|
|
"hover",
|
|
"panicky",
|
|
"scorch",
|
|
"diligent",
|
|
"hulking",
|
|
"ubiquitous",
|
|
"tedious",
|
|
"aberrant",
|
|
"file",
|
|
"accidental",
|
|
"mist",
|
|
"blue-eyed",
|
|
"trite",
|
|
"nondescript",
|
|
"cows",
|
|
"wait",
|
|
"test",
|
|
"snotty",
|
|
"amuck",
|
|
"jump",
|
|
"lackadaisical",
|
|
"grey",
|
|
"tawdry",
|
|
"strong",
|
|
"land",
|
|
"kind",
|
|
"star",
|
|
"ludicrous",
|
|
"stupid",
|
|
"telling",
|
|
"use",
|
|
"bruise",
|
|
"whirl",
|
|
"cream",
|
|
"harsh",
|
|
"aboriginal",
|
|
"substantial",
|
|
"brawny",
|
|
"tease",
|
|
"pollution",
|
|
"weather",
|
|
"degree",
|
|
"dry",
|
|
"film",
|
|
"obey",
|
|
"closed",
|
|
"dependent",
|
|
"want",
|
|
"undesirable",
|
|
"stamp",
|
|
"relax",
|
|
"foot",
|
|
"obscene",
|
|
"successful",
|
|
"wriggle",
|
|
"drain",
|
|
"greasy",
|
|
"escape",
|
|
"cross",
|
|
"odd",
|
|
"boring",
|
|
"absorbed",
|
|
"houses",
|
|
"suppose",
|
|
"suit",
|
|
"moon",
|
|
"ceaseless",
|
|
"explode",
|
|
"clap",
|
|
"pop",
|
|
"courageous",
|
|
"miss",
|
|
"notebook",
|
|
"delirious",
|
|
"form",
|
|
"pretty",
|
|
"sock",
|
|
"grotesque",
|
|
"noxious",
|
|
"record",
|
|
"stop",
|
|
"saw",
|
|
"thing",
|
|
"dislike",
|
|
"cloth",
|
|
"six",
|
|
"jar",
|
|
"unnatural",
|
|
"spiffy",
|
|
"itchy",
|
|
"secretary",
|
|
"move",
|
|
"certain",
|
|
"unkempt",
|
|
"sassy",
|
|
"queue",
|
|
"shrug",
|
|
"crow",
|
|
"heavenly",
|
|
"desert",
|
|
"screw",
|
|
"vessel",
|
|
"mug",
|
|
"encourage",
|
|
"icy",
|
|
"enthusiastic",
|
|
"throat",
|
|
"whistle",
|
|
"ignore",
|
|
"miniature",
|
|
"squeak",
|
|
"scarecrow",
|
|
"fluttering",
|
|
"hang",
|
|
"icicle",
|
|
"lie",
|
|
"juicy",
|
|
"empty",
|
|
"baseball",
|
|
"various",
|
|
"promise",
|
|
"abortive",
|
|
"descriptive",
|
|
"high",
|
|
"spy",
|
|
"faded",
|
|
"talk",
|
|
"air",
|
|
"messup",
|
|
"decorous",
|
|
"sneaky",
|
|
"mark",
|
|
"sack",
|
|
"ultra",
|
|
"chivalrous",
|
|
"lethal",
|
|
"expect",
|
|
"disgusted",
|
|
"reaction",
|
|
"fireman",
|
|
"private",
|
|
"ritzy",
|
|
"manage",
|
|
"actor",
|
|
"rely",
|
|
"uppity",
|
|
"thread",
|
|
"bat",
|
|
"space",
|
|
"underwear",
|
|
"blood",
|
|
"nine",
|
|
"maid",
|
|
"shelf",
|
|
"hanging",
|
|
"shop",
|
|
"prick",
|
|
"wound",
|
|
"sloppy",
|
|
"offer",
|
|
"increase",
|
|
"clear",
|
|
"slap",
|
|
"rude",
|
|
"poised",
|
|
"wretched",
|
|
"cause",
|
|
"quince",
|
|
"tame",
|
|
"remarkable",
|
|
"abject",
|
|
"sail",
|
|
"guide",
|
|
"subdued",
|
|
"spiky",
|
|
"debonair",
|
|
"chicken",
|
|
"tired",
|
|
"hum",
|
|
"land",
|
|
"scared",
|
|
"splendid",
|
|
"guess",
|
|
"cast",
|
|
"rub",
|
|
"magnificent",
|
|
"ants",
|
|
"overwrought",
|
|
"interfere",
|
|
"gorgeous",
|
|
"office",
|
|
"trade",
|
|
"sniff",
|
|
"melted",
|
|
"bore",
|
|
"point",
|
|
"pet",
|
|
"purple",
|
|
"brake",
|
|
"flavor",
|
|
"toe",
|
|
"prickly",
|
|
"zinc",
|
|
"homely",
|
|
"modern",
|
|
"kindly",
|
|
"whisper",
|
|
"bare",
|
|
"annoyed",
|
|
"glass",
|
|
"noisy",
|
|
"null",
|
|
"thoughtless",
|
|
"skirt",
|
|
"dock",
|
|
"rings",
|
|
"mind",
|
|
"neck",
|
|
"macho",
|
|
"wave",
|
|
"history",
|
|
"play",
|
|
"road",
|
|
"profit",
|
|
"word",
|
|
"opposite",
|
|
"dreary",
|
|
"governor",
|
|
"horse",
|
|
"trust",
|
|
"elbow",
|
|
"kiss",
|
|
"crayon",
|
|
"stitch",
|
|
"excited",
|
|
"needy",
|
|
"arrange",
|
|
"easy",
|
|
"alcoholic",
|
|
"safe",
|
|
"lumpy",
|
|
"monkey",
|
|
"smile",
|
|
"capable",
|
|
"untidy",
|
|
"extra-small",
|
|
"memory",
|
|
"selective",
|
|
"reproduce",
|
|
"old-fashioned",
|
|
"overrated",
|
|
"texture",
|
|
"knit",
|
|
"downtown",
|
|
"risk",
|
|
"pot",
|
|
"sofa",
|
|
"righteous",
|
|
"wren",
|
|
"pull",
|
|
"carry",
|
|
"aboard",
|
|
"listen",
|
|
"classy",
|
|
"thank",
|
|
"shocking",
|
|
"condition",
|
|
"root",
|
|
"attempt",
|
|
"swim",
|
|
"frog",
|
|
"hurt",
|
|
"army",
|
|
"title",
|
|
"handsomely",
|
|
"town",
|
|
"guiltless",
|
|
"thaw",
|
|
"spell",
|
|
"selfish",
|
|
"disturbed",
|
|
"tramp",
|
|
"girls",
|
|
"utopian",
|
|
"noiseless",
|
|
"trail",
|
|
"bashful",
|
|
"business",
|
|
"rhetorical",
|
|
"snail",
|
|
"sign",
|
|
"plausible",
|
|
"left",
|
|
"design",
|
|
"tall",
|
|
"violent",
|
|
"wasteful",
|
|
"beautiful",
|
|
"breezy",
|
|
"tap",
|
|
"murder",
|
|
"talented",
|
|
"needle",
|
|
"creator",
|
|
"imagine",
|
|
"flippant",
|
|
"dead",
|
|
"bone",
|
|
"coherent",
|
|
"relation",
|
|
"aromatic",
|
|
"mountainous",
|
|
"face",
|
|
"ask",
|
|
"picture",
|
|
"pedal",
|
|
"colour",
|
|
"obese",
|
|
"group",
|
|
"top",
|
|
"bubble",
|
|
"pinch",
|
|
"optimal",
|
|
"school",
|
|
"bathe",
|
|
"flagrant",
|
|
"check",
|
|
"deliver",
|
|
"pass",
|
|
"tan",
|
|
"crate",
|
|
"hose",
|
|
"debt",
|
|
"faulty",
|
|
"longing",
|
|
"hollow",
|
|
"invincible",
|
|
"afford",
|
|
"lovely",
|
|
"ticket",
|
|
"changeable",
|
|
"subtract",
|
|
"fumbling",
|
|
"responsible",
|
|
"confused",
|
|
"woman",
|
|
"touch",
|
|
"watch",
|
|
"zesty",
|
|
"library",
|
|
"jail",
|
|
"wrap",
|
|
"terrify",
|
|
"brick",
|
|
"popcorn",
|
|
"cooperative",
|
|
"peck",
|
|
"pocket",
|
|
"property",
|
|
"buzz",
|
|
"tiresome",
|
|
"digestion",
|
|
"exciting",
|
|
"nation",
|
|
"juvenile",
|
|
"shade",
|
|
"copper",
|
|
"wanting",
|
|
"deer",
|
|
"waste",
|
|
"man",
|
|
"join",
|
|
"spotty",
|
|
"amused",
|
|
"mountain",
|
|
"waggish",
|
|
"bushes",
|
|
"tense",
|
|
"river",
|
|
"heartbreaking",
|
|
"help",
|
|
"mine",
|
|
"narrow",
|
|
"smash",
|
|
"scrawny",
|
|
"tame",
|
|
"rain",
|
|
"playground",
|
|
"airport",
|
|
"astonishing",
|
|
"level",
|
|
"befitting",
|
|
"animal",
|
|
"heat",
|
|
"painful",
|
|
"cellar",
|
|
"ski",
|
|
"sedate",
|
|
"knowing",
|
|
"vigorous",
|
|
"change",
|
|
"eight",
|
|
"ship",
|
|
"work",
|
|
"strip",
|
|
"robin",
|
|
"tank",
|
|
"challenge",
|
|
"vacuous",
|
|
"representative",
|
|
"regret",
|
|
"tightfisted",
|
|
"erratic",
|
|
"club",
|
|
"imported",
|
|
"therapeutic",
|
|
"rainstorm",
|
|
"luxuriant",
|
|
"relieved",
|
|
"day",
|
|
"system",
|
|
"apologise",
|
|
"male",
|
|
"prepare",
|
|
"malicious",
|
|
"naive",
|
|
"whistle",
|
|
"curl",
|
|
"hobbies",
|
|
"trousers",
|
|
"stereotyped",
|
|
"dad",
|
|
"endurable",
|
|
"grass",
|
|
"hot",
|
|
"bomb",
|
|
"morning",
|
|
"guide",
|
|
"keen",
|
|
"plot",
|
|
"accept",
|
|
"disastrous",
|
|
"macabre",
|
|
"year",
|
|
"spicy",
|
|
"absorbing",
|
|
"sticks",
|
|
"efficient",
|
|
"drain",
|
|
"warm",
|
|
"rice",
|
|
"utter",
|
|
"fact",
|
|
"marked",
|
|
"ratty",
|
|
"chalk",
|
|
"towering",
|
|
"treat",
|
|
"nest",
|
|
"annoy",
|
|
"jealous",
|
|
"stamp",
|
|
"effect",
|
|
"cautious",
|
|
"jelly",
|
|
"feigned",
|
|
"gabby",
|
|
"corn",
|
|
"volleyball",
|
|
"pan",
|
|
"psychedelic",
|
|
"fairies",
|
|
"silent",
|
|
"zonked",
|
|
"bump",
|
|
"trouble",
|
|
"mass",
|
|
"queen",
|
|
"things",
|
|
"bury",
|
|
"sister",
|
|
"quiet",
|
|
"colossal",
|
|
"puncture",
|
|
"four",
|
|
"attend",
|
|
"love",
|
|
"wiry",
|
|
"vegetable",
|
|
"destruction",
|
|
"note",
|
|
"pies",
|
|
"resolute",
|
|
"load",
|
|
"fancy",
|
|
"tacky",
|
|
"periodic",
|
|
"abandoned",
|
|
"vivacious",
|
|
"blush",
|
|
"wrathful",
|
|
"miscreant",
|
|
"call",
|
|
"striped",
|
|
"wiggly",
|
|
"supreme",
|
|
"hand",
|
|
"impolite",
|
|
"rule",
|
|
"deserted",
|
|
"concern",
|
|
"cover",
|
|
"harbor",
|
|
"waiting",
|
|
"soggy",
|
|
"psychotic",
|
|
"ancient",
|
|
"sponge",
|
|
"domineering",
|
|
"elegant",
|
|
"impartial",
|
|
"unlock",
|
|
"abrasive",
|
|
"count",
|
|
"flight",
|
|
"neighborly",
|
|
"roof",
|
|
"bulb",
|
|
"auspicious",
|
|
"automatic",
|
|
"magic",
|
|
"sign",
|
|
"amusing",
|
|
"orange",
|
|
"branch",
|
|
"sulky",
|
|
"attack",
|
|
"fetch",
|
|
"number",
|
|
"jellyfish",
|
|
"start",
|
|
"alike",
|
|
"touch",
|
|
"sour",
|
|
"wary",
|
|
"minor",
|
|
"punish",
|
|
"connect",
|
|
"protest",
|
|
"pie",
|
|
"kaput",
|
|
"doubtful",
|
|
"friendly",
|
|
"simplistic",
|
|
"smart",
|
|
"vanish",
|
|
"applaud",
|
|
"jumbled",
|
|
"ready",
|
|
"yell",
|
|
"support",
|
|
"squash",
|
|
"raise",
|
|
"parallel",
|
|
"super",
|
|
"jazzy",
|
|
"crush",
|
|
"apathetic",
|
|
"water",
|
|
"food",
|
|
"thrill",
|
|
"permit",
|
|
"heady",
|
|
"last",
|
|
"mine",
|
|
"signal",
|
|
"smoke",
|
|
"preach",
|
|
"x-ray",
|
|
"name",
|
|
"birth",
|
|
"minute",
|
|
"steel",
|
|
"bedroom",
|
|
"female",
|
|
"acrid",
|
|
"riddle",
|
|
"attractive",
|
|
"earth",
|
|
"crack",
|
|
"muscle",
|
|
"alive",
|
|
"guarded",
|
|
"sweater",
|
|
"donkey",
|
|
"doubt",
|
|
"lettuce",
|
|
"magenta",
|
|
"live",
|
|
"farm",
|
|
"glib",
|
|
"bow",
|
|
"fascinated",
|
|
"friend",
|
|
"practise",
|
|
"remember",
|
|
"bleach",
|
|
"hungry",
|
|
"voiceless",
|
|
"pin",
|
|
"sparkling",
|
|
"report",
|
|
"arm",
|
|
"sad",
|
|
"shaggy",
|
|
"parcel",
|
|
"wail",
|
|
"flash",
|
|
"territory",
|
|
"functional",
|
|
"wise",
|
|
"screeching",
|
|
"appliance",
|
|
"future",
|
|
"appear",
|
|
"team",
|
|
"rabbit",
|
|
"porter",
|
|
"paint",
|
|
"flat",
|
|
"amusement",
|
|
"ocean",
|
|
"head",
|
|
"geese",
|
|
"wash",
|
|
"embarrassed",
|
|
"tub",
|
|
"boundless",
|
|
"freezing",
|
|
"mushy",
|
|
"surprise",
|
|
"temporary",
|
|
"marble",
|
|
"recondite",
|
|
"telephone",
|
|
"zipper",
|
|
"pine",
|
|
"reign",
|
|
"pump",
|
|
"tangy",
|
|
"reply",
|
|
"toys",
|
|
"purpose",
|
|
"songs",
|
|
"form",
|
|
"delicious",
|
|
"wood",
|
|
"horn",
|
|
"nutty",
|
|
"fruit",
|
|
"lumber",
|
|
"potato",
|
|
"cheat",
|
|
"cloudy",
|
|
"visit",
|
|
"reduce",
|
|
"destroy",
|
|
"deafening",
|
|
"full",
|
|
"warlike",
|
|
"mitten",
|
|
"cover",
|
|
"earthy",
|
|
"seashore",
|
|
"yarn",
|
|
"tenuous",
|
|
"pause",
|
|
"boil",
|
|
"dogs",
|
|
"tough",
|
|
"knife",
|
|
"shy",
|
|
"naughty",
|
|
"existence",
|
|
"fire",
|
|
"eminent",
|
|
"remove",
|
|
"juice",
|
|
"sleep",
|
|
"voyage",
|
|
"balance",
|
|
"unsightly",
|
|
"plough",
|
|
"ill-fated",
|
|
"pumped",
|
|
"motionless",
|
|
"allow",
|
|
"trade",
|
|
"warm",
|
|
"toad",
|
|
"wave",
|
|
"wall",
|
|
"pigs",
|
|
"circle",
|
|
"rejoice",
|
|
"ear",
|
|
"drink",
|
|
"found",
|
|
"taboo",
|
|
"object",
|
|
"old",
|
|
"temper",
|
|
"plant",
|
|
"public",
|
|
"picayune",
|
|
"blot",
|
|
"delight",
|
|
"carpenter",
|
|
"dispensable",
|
|
"tire",
|
|
"cow",
|
|
"furniture",
|
|
"rightful",
|
|
"mute",
|
|
"gentle",
|
|
"gifted",
|
|
"ragged",
|
|
"stiff",
|
|
"retire",
|
|
"compare",
|
|
"sable",
|
|
"hole",
|
|
"judicious",
|
|
"chilly",
|
|
"sparkle",
|
|
"futuristic",
|
|
"love",
|
|
"bubble",
|
|
"travel",
|
|
"name",
|
|
"numberless",
|
|
"succeed",
|
|
"acoustic",
|
|
"lowly",
|
|
"society",
|
|
"injure",
|
|
"agree",
|
|
"reason",
|
|
"party",
|
|
"wool",
|
|
"careful",
|
|
"hook",
|
|
"bell",
|
|
"ball",
|
|
"attach",
|
|
"scream",
|
|
"development",
|
|
"happy",
|
|
"appreciate",
|
|
"disagree",
|
|
"request",
|
|
"march",
|
|
"rampant",
|
|
"scrape",
|
|
"sack",
|
|
"hair",
|
|
"measure",
|
|
"owe",
|
|
"grubby",
|
|
"vein",
|
|
"boy",
|
|
"punishment",
|
|
"smoggy",
|
|
"wry",
|
|
"immense",
|
|
"shoe",
|
|
"pack",
|
|
"brash",
|
|
"cave",
|
|
"sincere",
|
|
"adorable",
|
|
"fantastic",
|
|
"attraction",
|
|
"racial",
|
|
"jittery",
|
|
"defiant",
|
|
"honey",
|
|
"paper",
|
|
"weight",
|
|
"bee",
|
|
"blind",
|
|
"birthday",
|
|
"toothsome",
|
|
"trick",
|
|
"guard",
|
|
"fog",
|
|
"handle",
|
|
"dirty",
|
|
"salt",
|
|
"rinse",
|
|
"nippy",
|
|
"observe",
|
|
"suggestion",
|
|
"weak",
|
|
"instinctive",
|
|
"frequent",
|
|
"detail",
|
|
"verse",
|
|
"quirky",
|
|
"scattered",
|
|
"toy",
|
|
"aware",
|
|
"distribution",
|
|
"repulsive",
|
|
"draconian",
|
|
"bucket",
|
|
"harm",
|
|
"radiate",
|
|
"bang",
|
|
"shrill",
|
|
"living",
|
|
"rhythm",
|
|
"obsequious",
|
|
"drum",
|
|
"inject",
|
|
"skate",
|
|
"beds",
|
|
"smash",
|
|
"order",
|
|
"stitch",
|
|
"ground",
|
|
"nosy",
|
|
"kick",
|
|
"dusty",
|
|
"home",
|
|
"rot",
|
|
"frame",
|
|
"jam",
|
|
"sky",
|
|
"soap",
|
|
"rescue",
|
|
"energetic",
|
|
"grape",
|
|
"massive",
|
|
"deeply",
|
|
"dazzling",
|
|
"park",
|
|
"pull",
|
|
"number",
|
|
"abundant",
|
|
"barbarous",
|
|
"drag",
|
|
"ajar",
|
|
"close",
|
|
"moan",
|
|
"haircut",
|
|
"shade",
|
|
"married",
|
|
"cats",
|
|
"thirsty",
|
|
"dirt",
|
|
"vagabond",
|
|
"fearful",
|
|
"squealing",
|
|
"squalid",
|
|
"zebra",
|
|
"murky",
|
|
"sheet",
|
|
"fat",
|
|
"follow",
|
|
"bikes",
|
|
"unpack",
|
|
"materialistic",
|
|
"surprise",
|
|
"arch",
|
|
"selection",
|
|
"acoustics",
|
|
"helpless",
|
|
"thoughtful",
|
|
"cry",
|
|
"quarrelsome",
|
|
"arrogant",
|
|
"illegal",
|
|
"sudden",
|
|
"elite",
|
|
"tomatoes",
|
|
"spoil",
|
|
"flower",
|
|
"shivering",
|
|
"front",
|
|
"caption",
|
|
"volcano",
|
|
"ugliest",
|
|
"ambitious",
|
|
"pickle",
|
|
"interrupt",
|
|
"nervous",
|
|
"approve",
|
|
"messy",
|
|
"dust",
|
|
"oceanic",
|
|
"brass",
|
|
"tremble",
|
|
"fine",
|
|
"nerve",
|
|
"lunchroom",
|
|
"hard",
|
|
"engine",
|
|
"erect",
|
|
"flower",
|
|
"cynical",
|
|
"irritating",
|
|
"tight",
|
|
"cobweb",
|
|
"gray",
|
|
"invention",
|
|
"snatch",
|
|
"account",
|
|
"sharp",
|
|
"spooky",
|
|
"squeamish",
|
|
"eatable",
|
|
"share",
|
|
"need",
|
|
"moaning",
|
|
"suspect",
|
|
"rush",
|
|
"rural",
|
|
"false",
|
|
"float",
|
|
"bite",
|
|
"careless",
|
|
"sidewalk",
|
|
"cowardly",
|
|
"stroke",
|
|
"educated",
|
|
"ugly",
|
|
"type",
|
|
"wandering",
|
|
"bolt",
|
|
"mint",
|
|
"fit",
|
|
"large",
|
|
"extra-large",
|
|
"defeated",
|
|
"kitty",
|
|
"tacit",
|
|
"abiding",
|
|
"grandfather",
|
|
"trains",
|
|
"lamp",
|
|
"habitual",
|
|
"fast",
|
|
"offbeat",
|
|
"accurate",
|
|
"many",
|
|
"fortunate",
|
|
"lyrical",
|
|
"charge",
|
|
"illustrious",
|
|
"transport",
|
|
"wakeful",
|
|
"cable",
|
|
"ordinary",
|
|
"string",
|
|
"question",
|
|
"train",
|
|
"fancy",
|
|
"kick",
|
|
"enchanting",
|
|
"jobless",
|
|
"ahead",
|
|
"comparison",
|
|
"loose",
|
|
"dance",
|
|
"add",
|
|
"wonder",
|
|
"stale",
|
|
"earn",
|
|
"reflective",
|
|
"bright",
|
|
"true",
|
|
"statuesque",
|
|
"amount",
|
|
"matter",
|
|
"repair",
|
|
"care",
|
|
"ruin",
|
|
"terrible",
|
|
"elastic",
|
|
"spiders",
|
|
"craven",
|
|
"lamentable",
|
|
"decision",
|
|
"swing",
|
|
"connection",
|
|
"gaudy",
|
|
"knowledge",
|
|
"cheap",
|
|
"lazy",
|
|
"step",
|
|
"dinner",
|
|
"rod",
|
|
"agreement",
|
|
"comb",
|
|
"mean",
|
|
"past",
|
|
"knotty",
|
|
"busy",
|
|
"quicksand",
|
|
"match",
|
|
"early",
|
|
"long",
|
|
"onerous",
|
|
"ambiguous",
|
|
"worried",
|
|
"spade",
|
|
"happen",
|
|
"crook",
|
|
"dapper",
|
|
"grate",
|
|
"announce",
|
|
"plate",
|
|
"haunt",
|
|
"friction",
|
|
"actually",
|
|
"chance",
|
|
"example",
|
|
"rapid",
|
|
"zealous",
|
|
"necessary",
|
|
"ink",
|
|
"mere",
|
|
"shock",
|
|
"huge",
|
|
"jaded",
|
|
"spill",
|
|
"store",
|
|
"fuzzy",
|
|
"table",
|
|
"bottle",
|
|
"halting",
|
|
"spark",
|
|
"end",
|
|
"remain",
|
|
"transport",
|
|
"seat",
|
|
"leg",
|
|
"long-term",
|
|
"clip",
|
|
"grumpy",
|
|
"shake",
|
|
"walk",
|
|
"try",
|
|
"action",
|
|
"soup",
|
|
"short",
|
|
"hurry",
|
|
"square",
|
|
"belligerent",
|
|
"thankful",
|
|
"beginner",
|
|
"small",
|
|
"bumpy",
|
|
"silly",
|
|
"badge",
|
|
"marvelous",
|
|
"wealth",
|
|
"open",
|
|
"unequal",
|
|
"scatter",
|
|
"pest",
|
|
"fool",
|
|
"step",
|
|
"groovy",
|
|
"childlike",
|
|
"door",
|
|
"bouncy",
|
|
"believe",
|
|
"incredible",
|
|
"box",
|
|
"unhealthy",
|
|
"swanky",
|
|
"abrupt",
|
|
"depressed",
|
|
"flaky",
|
|
"famous",
|
|
"detailed",
|
|
"regret",
|
|
"envious",
|
|
"natural",
|
|
"apparel",
|
|
"spare",
|
|
"mark",
|
|
"ten",
|
|
"power",
|
|
"glistening",
|
|
"arrive",
|
|
"animated",
|
|
"slip",
|
|
"heap",
|
|
"shaky",
|
|
"unfasten",
|
|
"contain",
|
|
"inexpensive",
|
|
"introduce",
|
|
"shallow",
|
|
"rule",
|
|
"gather",
|
|
"pump",
|
|
"humorous",
|
|
"acceptable",
|
|
"womanly",
|
|
"giddy",
|
|
"silk",
|
|
"yoke",
|
|
"straw",
|
|
"invite",
|
|
"one",
|
|
"red",
|
|
"growth",
|
|
"unadvised",
|
|
"measly",
|
|
"flap",
|
|
"puzzled",
|
|
"regular",
|
|
"painstaking",
|
|
"little",
|
|
"plain",
|
|
"tumble",
|
|
"rest",
|
|
"fabulous",
|
|
"melt",
|
|
"label",
|
|
"truculent",
|
|
"internal",
|
|
"passenger",
|
|
"zippy",
|
|
"bright",
|
|
"earsplitting",
|
|
"tooth",
|
|
"veil",
|
|
"grip",
|
|
"square",
|
|
"stuff",
|
|
"gate",
|
|
"level",
|
|
"stone",
|
|
"observation",
|
|
"time",
|
|
"workable",
|
|
"bird",
|
|
"realise",
|
|
"spotted",
|
|
"coast",
|
|
"quiver",
|
|
"rebel",
|
|
"entertain",
|
|
"rotten",
|
|
"loss",
|
|
"collect",
|
|
"meal",
|
|
"satisfy",
|
|
"military",
|
|
"bake",
|
|
"cagey",
|
|
"redundant",
|
|
"treatment",
|
|
"knock",
|
|
"blink",
|
|
"scale",
|
|
"board",
|
|
"fair",
|
|
"nebulous",
|
|
"sip",
|
|
"homeless",
|
|
"place",
|
|
"complain",
|
|
"joke",
|
|
"bat",
|
|
"winter",
|
|
"choke",
|
|
"frantic",
|
|
"chubby",
|
|
"highfalutin",
|
|
"troubled",
|
|
"whole",
|
|
"rose",
|
|
"delightful",
|
|
"loaf",
|
|
"afraid",
|
|
"sturdy",
|
|
"class",
|
|
"cultured",
|
|
"yielding",
|
|
"broken",
|
|
"kittens",
|
|
"absurd",
|
|
"discovery",
|
|
"next",
|
|
"disarm",
|
|
"dangerous",
|
|
"lively",
|
|
"reflect",
|
|
"chief",
|
|
"teeny",
|
|
"pencil",
|
|
"ban",
|
|
"grade",
|
|
"size",
|
|
"dashing",
|
|
"thought",
|
|
"breath",
|
|
"empty",
|
|
"hellish",
|
|
"shock",
|
|
"sea",
|
|
"weary",
|
|
"payment",
|
|
"limping",
|
|
"premium",
|
|
"grateful",
|
|
"somber",
|
|
"tax",
|
|
"coach",
|
|
"vulgar",
|
|
"stretch",
|
|
"tow",
|
|
"branch",
|
|
"insurance",
|
|
"yam",
|
|
"stormy",
|
|
"wish",
|
|
"snow",
|
|
"cute",
|
|
"milky",
|
|
"battle",
|
|
"far",
|
|
"roasted",
|
|
"slip",
|
|
"adamant",
|
|
"awake",
|
|
"employ",
|
|
"tangible",
|
|
"tickle",
|
|
"jog",
|
|
"hysterical",
|
|
"meddle",
|
|
"parsimonious",
|
|
"judge",
|
|
"educate",
|
|
"respect",
|
|
"sound",
|
|
"oven",
|
|
"gratis",
|
|
"station",
|
|
"train",
|
|
"purring",
|
|
"steady",
|
|
"carriage",
|
|
"humdrum",
|
|
"voracious",
|
|
"jolly",
|
|
"brainy",
|
|
"proud",
|
|
"elfin",
|
|
"cure",
|
|
"motion",
|
|
"record",
|
|
"quizzical",
|
|
"pail",
|
|
"bike",
|
|
"faithful",
|
|
"approval",
|
|
"vague",
|
|
"fall",
|
|
"store",
|
|
"normal",
|
|
"rock",
|
|
"bear",
|
|
"bounce",
|
|
"giant",
|
|
"satisfying",
|
|
"crooked",
|
|
"lopsided",
|
|
"vest",
|
|
"separate",
|
|
"sneeze",
|
|
"teaching",
|
|
"general",
|
|
"meat",
|
|
"festive",
|
|
"historical",
|
|
"line",
|
|
"north",
|
|
"tip",
|
|
"son",
|
|
"damaging",
|
|
"nimble",
|
|
"broad",
|
|
"list",
|
|
"confuse",
|
|
"first",
|
|
"deserve",
|
|
"steep",
|
|
"last",
|
|
"rich",
|
|
"oval",
|
|
"thick",
|
|
"glow",
|
|
"great",
|
|
"clammy",
|
|
"cheer",
|
|
"untidy",
|
|
"scientific",
|
|
"noise",
|
|
"stomach",
|
|
"undress",
|
|
"big",
|
|
"bite-sized",
|
|
"enter",
|
|
"cake",
|
|
"aloof",
|
|
"abnormal",
|
|
"month",
|
|
"grab",
|
|
"well-groomed",
|
|
"silver",
|
|
"art",
|
|
"berry",
|
|
"giraffe",
|
|
"complete",
|
|
"billowy",
|
|
"thumb",
|
|
"squeal",
|
|
"crib",
|
|
"discussion",
|
|
"even",
|
|
"stretch",
|
|
"mellow",
|
|
"angry",
|
|
"grouchy",
|
|
"absent",
|
|
"snow",
|
|
"middle",
|
|
"stingy",
|
|
"mourn",
|
|
"deep",
|
|
"honorable",
|
|
"nice",
|
|
"verdant",
|
|
"reach",
|
|
"lavish",
|
|
"sin",
|
|
"interest",
|
|
"whine",
|
|
"tug",
|
|
"vengeful",
|
|
"rhyme",
|
|
"stay",
|
|
"upset",
|
|
"hesitant",
|
|
"tent",
|
|
"wire",
|
|
"gold",
|
|
"momentous",
|
|
"yellow",
|
|
"cap",
|
|
"delicate",
|
|
"youthful",
|
|
"twig",
|
|
"burly",
|
|
"devilish",
|
|
"chess",
|
|
"wide",
|
|
"misty",
|
|
"useful",
|
|
"memorise",
|
|
"madly",
|
|
"plants",
|
|
"spectacular",
|
|
"accessible",
|
|
"collar",
|
|
"truck",
|
|
"harmony",
|
|
"uncovered",
|
|
"beef",
|
|
"low",
|
|
"channel",
|
|
"abusive",
|
|
"analyse",
|
|
"observant",
|
|
"snobbish",
|
|
"duck",
|
|
"excellent",
|
|
"intend",
|
|
"wreck",
|
|
"testy",
|
|
"care",
|
|
"shoes",
|
|
"charming",
|
|
"demonic",
|
|
"can",
|
|
"wipe",
|
|
"acidic",
|
|
"watch",
|
|
"decisive",
|
|
"brave",
|
|
"greet",
|
|
"imminent",
|
|
"influence",
|
|
"oranges",
|
|
"seal",
|
|
"eggs",
|
|
"knowledgeable",
|
|
"ashamed",
|
|
"shiny",
|
|
"inconclusive",
|
|
"remind",
|
|
"house",
|
|
"solid",
|
|
"quixotic",
|
|
"describe",
|
|
"support",
|
|
];
|
|
return randomElement(words);
|
|
}
|
|
|
|
function execCommand(client, command, options = {}) {
|
|
let exePath = "node " + joplinAppPath;
|
|
let cmd = exePath + " --update-geolocation-disabled --env dev --log-level debug --profile " + client.profileDir + " " + command;
|
|
logger.info(client.id + ": " + command);
|
|
|
|
if (options.killAfter) {
|
|
logger.info("Kill after: " + options.killAfter);
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
let childProcess = exec(cmd, (error, stdout, stderr) => {
|
|
if (error) {
|
|
if (error.signal == "SIGTERM") {
|
|
resolve("Process was killed");
|
|
} else {
|
|
logger.error(stderr);
|
|
reject(error);
|
|
}
|
|
} else {
|
|
resolve(stdout.trim());
|
|
}
|
|
});
|
|
|
|
if (options.killAfter) {
|
|
setTimeout(() => {
|
|
logger.info("Sending kill signal...");
|
|
childProcess.kill();
|
|
}, options.killAfter);
|
|
}
|
|
});
|
|
}
|
|
|
|
async function clientItems(client) {
|
|
let itemsJson = await execCommand(client, "dump");
|
|
try {
|
|
return JSON.parse(itemsJson);
|
|
} catch (error) {
|
|
throw new Error("Cannot parse JSON: " + itemsJson);
|
|
}
|
|
}
|
|
|
|
function randomTag(items) {
|
|
let tags = [];
|
|
for (let i = 0; i < items.length; i++) {
|
|
if (items[i].type_ != 5) continue;
|
|
tags.push(items[i]);
|
|
}
|
|
|
|
return randomElement(tags);
|
|
}
|
|
|
|
function randomNote(items) {
|
|
let notes = [];
|
|
for (let i = 0; i < items.length; i++) {
|
|
if (items[i].type_ != 1) continue;
|
|
notes.push(items[i]);
|
|
}
|
|
|
|
return randomElement(notes);
|
|
}
|
|
|
|
async function execRandomCommand(client) {
|
|
let possibleCommands = [
|
|
["mkbook {word}", 40], // CREATE FOLDER
|
|
["mknote {word}", 70], // CREATE NOTE
|
|
[
|
|
async () => {
|
|
// DELETE RANDOM ITEM
|
|
let items = await clientItems(client);
|
|
let item = randomElement(items);
|
|
if (!item) return;
|
|
|
|
if (item.type_ == 1) {
|
|
return execCommand(client, "rm -f " + item.id);
|
|
} else if (item.type_ == 2) {
|
|
return execCommand(client, "rm -r -f " + item.id);
|
|
} else if (item.type_ == 5) {
|
|
// tag
|
|
} else {
|
|
throw new Error("Unknown type: " + item.type_);
|
|
}
|
|
},
|
|
30,
|
|
],
|
|
[
|
|
async () => {
|
|
// SYNC
|
|
let avgSyncDuration = averageSyncDuration();
|
|
let options = {};
|
|
if (!isNaN(avgSyncDuration)) {
|
|
if (Math.random() >= 0.5) {
|
|
options.killAfter = avgSyncDuration * Math.random();
|
|
}
|
|
}
|
|
return execCommand(client, "sync --random-failures", options);
|
|
},
|
|
30,
|
|
],
|
|
[
|
|
async () => {
|
|
// UPDATE RANDOM ITEM
|
|
let items = await clientItems(client);
|
|
let item = randomNote(items);
|
|
if (!item) return;
|
|
|
|
return execCommand(client, "set " + item.id + ' title "' + randomWord() + '"');
|
|
},
|
|
50,
|
|
],
|
|
[
|
|
async () => {
|
|
// ADD TAG
|
|
let items = await clientItems(client);
|
|
let note = randomNote(items);
|
|
if (!note) return;
|
|
|
|
let tag = randomTag(items);
|
|
let tagTitle = !tag || Math.random() >= 0.9 ? "tag-" + randomWord() : tag.title;
|
|
|
|
return execCommand(client, "tag add " + tagTitle + " " + note.id);
|
|
},
|
|
50,
|
|
],
|
|
];
|
|
|
|
let cmd = null;
|
|
while (true) {
|
|
cmd = randomElement(possibleCommands);
|
|
let r = 1 + Math.floor(Math.random() * 100);
|
|
if (r <= cmd[1]) break;
|
|
}
|
|
|
|
cmd = cmd[0];
|
|
|
|
if (typeof cmd === "function") {
|
|
return cmd();
|
|
} else {
|
|
cmd = cmd.replace("{word}", randomWord());
|
|
return execCommand(client, cmd);
|
|
}
|
|
}
|
|
|
|
function averageSyncDuration() {
|
|
return lodash.mean(syncDurations);
|
|
}
|
|
|
|
function randomNextCheckTime() {
|
|
let output = time.unixMs() + 1000 + Math.random() * 1000 * 120;
|
|
logger.info("Next sync check: " + time.unixMsToIso(output) + " (" + Math.round((output - time.unixMs()) / 1000) + " sec.)");
|
|
return output;
|
|
}
|
|
|
|
function findItem(items, itemId) {
|
|
for (let i = 0; i < items.length; i++) {
|
|
if (items[i].id == itemId) return items[i];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function compareItems(item1, item2) {
|
|
let output = [];
|
|
for (let n in item1) {
|
|
if (!item1.hasOwnProperty(n)) continue;
|
|
let p1 = item1[n];
|
|
let p2 = item2[n];
|
|
|
|
if (n == "notes_") {
|
|
p1.sort();
|
|
p2.sort();
|
|
if (JSON.stringify(p1) !== JSON.stringify(p2)) {
|
|
output.push(n);
|
|
}
|
|
} else {
|
|
if (p1 !== p2) output.push(n);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
function findMissingItems_(items1, items2) {
|
|
let output = [];
|
|
|
|
for (let i = 0; i < items1.length; i++) {
|
|
let item1 = items1[i];
|
|
let found = false;
|
|
for (let j = 0; j < items2.length; j++) {
|
|
let item2 = items2[j];
|
|
if (item1.id == item2.id) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
output.push(item1);
|
|
}
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
function findMissingItems(items1, items2) {
|
|
return [findMissingItems_(items1, items2), findMissingItems_(items2, items1)];
|
|
}
|
|
|
|
async function compareClientItems(clientItems) {
|
|
let itemCounts = [];
|
|
for (let i = 0; i < clientItems.length; i++) {
|
|
let items = clientItems[i];
|
|
itemCounts.push(items.length);
|
|
}
|
|
logger.info("Item count: " + itemCounts.join(", "));
|
|
|
|
let missingItems = findMissingItems(clientItems[0], clientItems[1]);
|
|
if (missingItems[0].length || missingItems[1].length) {
|
|
logger.error("Items are different");
|
|
logger.error(missingItems);
|
|
process.exit(1);
|
|
}
|
|
|
|
let differences = [];
|
|
let items = clientItems[0];
|
|
for (let i = 0; i < items.length; i++) {
|
|
let item1 = items[i];
|
|
for (let clientId = 1; clientId < clientItems.length; clientId++) {
|
|
let item2 = findItem(clientItems[clientId], item1.id);
|
|
if (!item2) {
|
|
logger.error("Item not found on client " + clientId + ":");
|
|
logger.error(item1);
|
|
process.exit(1);
|
|
}
|
|
|
|
let diff = compareItems(item1, item2);
|
|
if (diff.length) {
|
|
differences.push({
|
|
item1: JSON.stringify(item1),
|
|
item2: JSON.stringify(item2),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (differences.length) {
|
|
logger.error("Found differences between items:");
|
|
logger.error(differences);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
async function main(argv) {
|
|
await fs.remove(syncDir);
|
|
|
|
let clients = await createClients();
|
|
let activeCommandCounts = [];
|
|
let clientId = 0;
|
|
|
|
for (let i = 0; i < clients.length; i++) {
|
|
clients[i].activeCommandCount = 0;
|
|
}
|
|
|
|
function handleCommand(clientId) {
|
|
if (clients[clientId].activeCommandCount >= 1) return;
|
|
|
|
clients[clientId].activeCommandCount++;
|
|
|
|
execRandomCommand(clients[clientId])
|
|
.catch(error => {
|
|
logger.info("Client " + clientId + ":");
|
|
logger.error(error);
|
|
})
|
|
.then(r => {
|
|
if (r) {
|
|
logger.info("Client " + clientId + ":\n" + r.trim());
|
|
}
|
|
clients[clientId].activeCommandCount--;
|
|
});
|
|
}
|
|
|
|
let nextSyncCheckTime = randomNextCheckTime();
|
|
let state = "commands";
|
|
|
|
setInterval(async () => {
|
|
if (state == "waitForSyncCheck") return;
|
|
|
|
if (state == "syncCheck") {
|
|
state = "waitForSyncCheck";
|
|
let clientItems = [];
|
|
// Up to 3 sync operations must be performed by each clients in order for them
|
|
// to be perfectly in sync - in order for each items to send their changes
|
|
// and get those from the other clients, and to also get changes that are
|
|
// made as a result of a sync operation (eg. renaming a folder that conflicts
|
|
// with another one).
|
|
for (let loopCount = 0; loopCount < 3; loopCount++) {
|
|
for (let i = 0; i < clients.length; i++) {
|
|
let beforeTime = time.unixMs();
|
|
await execCommand(clients[i], "sync");
|
|
syncDurations.push(time.unixMs() - beforeTime);
|
|
if (syncDurations.length > 20) syncDurations.splice(0, 1);
|
|
if (loopCount === 2) {
|
|
let dump = await execCommand(clients[i], "dump");
|
|
clientItems[i] = JSON.parse(dump);
|
|
}
|
|
}
|
|
}
|
|
|
|
await compareClientItems(clientItems);
|
|
|
|
nextSyncCheckTime = randomNextCheckTime();
|
|
state = "commands";
|
|
return;
|
|
}
|
|
|
|
if (state == "waitForClients") {
|
|
for (let i = 0; i < clients.length; i++) {
|
|
if (clients[i].activeCommandCount > 0) return;
|
|
}
|
|
|
|
state = "syncCheck";
|
|
return;
|
|
}
|
|
|
|
if (state == "commands") {
|
|
if (nextSyncCheckTime <= time.unixMs()) {
|
|
state = "waitForClients";
|
|
return;
|
|
}
|
|
|
|
handleCommand(clientId);
|
|
clientId++;
|
|
if (clientId >= clients.length) clientId = 0;
|
|
}
|
|
}, 100);
|
|
}
|
|
|
|
main(process.argv).catch(error => {
|
|
logger.error(error);
|
|
});
|