base_config: Don't throw if loaded config file is empty
This commit is contained in:
parent
53bc13a401
commit
be862afd1a
3 changed files with 90 additions and 9 deletions
|
@ -13,6 +13,9 @@ export type ConfigType = {
|
||||||
set: (keyPath: string, value: unknown) => void;
|
set: (keyPath: string, value: unknown) => void;
|
||||||
get: (keyPath: string) => unknown;
|
get: (keyPath: string) => unknown;
|
||||||
remove: () => void;
|
remove: () => void;
|
||||||
|
|
||||||
|
// Test-only
|
||||||
|
_getCachedValue: () => InternalConfigType | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function start(
|
export function start(
|
||||||
|
@ -21,10 +24,11 @@ export function start(
|
||||||
options?: { allowMalformedOnStartup?: boolean }
|
options?: { allowMalformedOnStartup?: boolean }
|
||||||
): ConfigType {
|
): ConfigType {
|
||||||
let cachedValue: InternalConfigType | undefined;
|
let cachedValue: InternalConfigType | undefined;
|
||||||
|
let incomingJson: string | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const text = readFileSync(targetPath, ENCODING);
|
incomingJson = readFileSync(targetPath, ENCODING);
|
||||||
cachedValue = JSON.parse(text);
|
cachedValue = incomingJson ? JSON.parse(incomingJson) : undefined;
|
||||||
console.log(`config/get: Successfully read ${name} config file`);
|
console.log(`config/get: Successfully read ${name} config file`);
|
||||||
|
|
||||||
if (!cachedValue) {
|
if (!cachedValue) {
|
||||||
|
@ -38,9 +42,15 @@ export function start(
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
if (incomingJson) {
|
||||||
`config/get: Did not find ${name} config file, cache is now empty object`
|
console.log(
|
||||||
);
|
`config/get: ${name} config file was malformed, starting afresh`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`config/get: Did not find ${name} config file (or it was empty), cache is now empty object`
|
||||||
|
);
|
||||||
|
}
|
||||||
cachedValue = Object.create(null);
|
cachedValue = Object.create(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +65,8 @@ export function start(
|
||||||
|
|
||||||
set(cachedValue, keyPath, value);
|
set(cachedValue, keyPath, value);
|
||||||
console.log(`config/set: Saving ${name} config to disk`);
|
console.log(`config/set: Saving ${name} config to disk`);
|
||||||
const text = JSON.stringify(cachedValue, null, ' ');
|
const outgoingJson = JSON.stringify(cachedValue, null, ' ');
|
||||||
writeFileSync(targetPath, text, ENCODING);
|
writeFileSync(targetPath, outgoingJson, ENCODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove(): void {
|
function remove(): void {
|
||||||
|
@ -69,5 +79,6 @@ export function start(
|
||||||
set: ourSet,
|
set: ourSet,
|
||||||
get: ourGet,
|
get: ourGet,
|
||||||
remove,
|
remove,
|
||||||
|
_getCachedValue: () => cachedValue,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import * as GlobalErrors from './global_errors';
|
||||||
import { setup as setupSpellChecker } from './spell_check';
|
import { setup as setupSpellChecker } from './spell_check';
|
||||||
import { redactAll, addSensitivePath } from '../ts/util/privacy';
|
import { redactAll, addSensitivePath } from '../ts/util/privacy';
|
||||||
import { consoleLogger } from '../ts/util/consoleLogger';
|
import { consoleLogger } from '../ts/util/consoleLogger';
|
||||||
import { remove as removeUserConfig } from './user_config';
|
|
||||||
|
|
||||||
import './startup_config';
|
import './startup_config';
|
||||||
|
|
||||||
|
@ -1318,7 +1317,7 @@ const onDatabaseError = async (error: string) => {
|
||||||
clipboard.writeText(`Database startup error:\n\n${redactAll(error)}`);
|
clipboard.writeText(`Database startup error:\n\n${redactAll(error)}`);
|
||||||
} else {
|
} else {
|
||||||
await sql.removeDB();
|
await sql.removeDB();
|
||||||
removeUserConfig();
|
userConfig.remove();
|
||||||
app.relaunch();
|
app.relaunch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
71
ts/test-node/app/base_config_test.ts
Normal file
71
ts/test-node/app/base_config_test.ts
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import { tmpdir } from 'os';
|
||||||
|
import { writeFileSync, unlinkSync } from 'fs';
|
||||||
|
|
||||||
|
import { v4 as generateGuid } from 'uuid';
|
||||||
|
import { assert } from 'chai';
|
||||||
|
|
||||||
|
import { start } from '../../../app/base_config';
|
||||||
|
|
||||||
|
describe('base_config', () => {
|
||||||
|
let targetFile: string | undefined;
|
||||||
|
|
||||||
|
function getNewPath() {
|
||||||
|
return `${tmpdir()}/${generateGuid()}.txt`;
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (targetFile) {
|
||||||
|
unlinkSync(targetFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw if file is missing', () => {
|
||||||
|
const missingFile = getNewPath();
|
||||||
|
const { _getCachedValue } = start('test', missingFile);
|
||||||
|
|
||||||
|
assert.deepEqual(_getCachedValue(), Object.create(null));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully loads config file', () => {
|
||||||
|
targetFile = getNewPath();
|
||||||
|
|
||||||
|
const config = { a: 1, b: 2 };
|
||||||
|
writeFileSync(targetFile, JSON.stringify(config));
|
||||||
|
const { _getCachedValue } = start('test', targetFile);
|
||||||
|
|
||||||
|
assert.deepEqual(_getCachedValue(), config);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws if file is malformed', () => {
|
||||||
|
targetFile = getNewPath();
|
||||||
|
|
||||||
|
writeFileSync(targetFile, '{{ malformed JSON');
|
||||||
|
|
||||||
|
const fileForClosure = targetFile;
|
||||||
|
assert.throws(() => start('test', fileForClosure));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw if file is empty', () => {
|
||||||
|
targetFile = getNewPath();
|
||||||
|
|
||||||
|
writeFileSync(targetFile, '');
|
||||||
|
|
||||||
|
const { _getCachedValue } = start('test', targetFile);
|
||||||
|
|
||||||
|
assert.deepEqual(_getCachedValue(), Object.create(null));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw if file is malformed, with allowMalformedOnStartup', () => {
|
||||||
|
targetFile = getNewPath();
|
||||||
|
|
||||||
|
writeFileSync(targetFile, '{{ malformed JSON');
|
||||||
|
const { _getCachedValue } = start('test', targetFile, {
|
||||||
|
allowMalformedOnStartup: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(_getCachedValue(), Object.create(null));
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue