mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
2403 lines
33 KiB
JavaScript
2403 lines
33 KiB
JavaScript
'use strict';
|
|
|
|
const { time } = require('lib/time-utils.js');
|
|
const Logger = require('lib/Logger').default;
|
|
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`;
|
|
const 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() {
|
|
const output = [];
|
|
const promises = [];
|
|
for (let clientId = 0; clientId < 2; clientId++) {
|
|
const 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 = {}) {
|
|
const exePath = `node ${joplinAppPath}`;
|
|
const 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) => {
|
|
const 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) {
|
|
const itemsJson = await execCommand(client, 'dump');
|
|
try {
|
|
return JSON.parse(itemsJson);
|
|
} catch (error) {
|
|
throw new Error(`Cannot parse JSON: ${itemsJson}`);
|
|
}
|
|
}
|
|
|
|
function randomTag(items) {
|
|
const 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) {
|
|
const 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) {
|
|
const possibleCommands = [
|
|
['mkbook {word}', 40], // CREATE FOLDER
|
|
['mknote {word}', 70], // CREATE NOTE
|
|
[
|
|
async () => {
|
|
// DELETE RANDOM ITEM
|
|
const items = await clientItems(client);
|
|
const 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
|
|
const avgSyncDuration = averageSyncDuration();
|
|
const 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
|
|
const items = await clientItems(client);
|
|
const item = randomNote(items);
|
|
if (!item) return;
|
|
|
|
return execCommand(client, `set ${item.id} title "${randomWord()}"`);
|
|
},
|
|
50,
|
|
],
|
|
[
|
|
async () => {
|
|
// ADD TAG
|
|
const items = await clientItems(client);
|
|
const note = randomNote(items);
|
|
if (!note) return;
|
|
|
|
const tag = randomTag(items);
|
|
const 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);
|
|
const 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() {
|
|
const 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) {
|
|
const output = [];
|
|
for (const n in item1) {
|
|
if (!item1.hasOwnProperty(n)) continue;
|
|
const p1 = item1[n];
|
|
const 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) {
|
|
const output = [];
|
|
|
|
for (let i = 0; i < items1.length; i++) {
|
|
const item1 = items1[i];
|
|
let found = false;
|
|
for (let j = 0; j < items2.length; j++) {
|
|
const 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) {
|
|
const itemCounts = [];
|
|
for (let i = 0; i < clientItems.length; i++) {
|
|
const items = clientItems[i];
|
|
itemCounts.push(items.length);
|
|
}
|
|
logger.info(`Item count: ${itemCounts.join(', ')}`);
|
|
|
|
const missingItems = findMissingItems(clientItems[0], clientItems[1]);
|
|
if (missingItems[0].length || missingItems[1].length) {
|
|
logger.error('Items are different');
|
|
logger.error(missingItems);
|
|
process.exit(1);
|
|
}
|
|
|
|
const differences = [];
|
|
const items = clientItems[0];
|
|
for (let i = 0; i < items.length; i++) {
|
|
const item1 = items[i];
|
|
for (let clientId = 1; clientId < clientItems.length; clientId++) {
|
|
const item2 = findItem(clientItems[clientId], item1.id);
|
|
if (!item2) {
|
|
logger.error(`Item not found on client ${clientId}:`);
|
|
logger.error(item1);
|
|
process.exit(1);
|
|
}
|
|
|
|
const 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() {
|
|
await fs.remove(syncDir);
|
|
|
|
const clients = await createClients();
|
|
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';
|
|
const 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++) {
|
|
const beforeTime = time.unixMs();
|
|
await execCommand(clients[i], 'sync');
|
|
syncDurations.push(time.unixMs() - beforeTime);
|
|
if (syncDurations.length > 20) syncDurations.splice(0, 1);
|
|
if (loopCount === 2) {
|
|
const dump = await execCommand(clients[i], 'dump');
|
|
clientItems[i] = JSON.parse(dump);
|
|
}
|
|
}
|
|
}
|
|
|
|
await compareClientItems(clientItems);
|
|
|
|
nextSyncCheckTime = randomNextCheckTime();
|
|
// eslint-disable-next-line require-atomic-updates
|
|
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);
|
|
});
|