diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2020-11-23 12:55:29 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2020-11-23 12:55:29 +0100 |
| commit | 6b95ceead2b6712d05a836e50395b754cc8605ad (patch) | |
| tree | 7d0cd5d27ab4f46208ef0979e0943a9f7bff18f8 | |
| parent | 410cf70afb817488233dce1018d38fe734665d53 (diff) | |
| parent | 86af950a735ad5aef786a92fa0b0f26bb482c38e (diff) | |
| download | mullvadvpn-6b95ceead2b6712d05a836e50395b754cc8605ad.tar.xz mullvadvpn-6b95ceead2b6712d05a836e50395b754cc8605ad.zip | |
Merge branch 'change-renderer-log-file-name'
| -rw-r--r-- | gui/src/main/index.ts | 2 | ||||
| -rw-r--r-- | gui/src/shared/logging.ts | 46 | ||||
| -rw-r--r-- | gui/test/logging.spec.ts | 81 |
3 files changed, 119 insertions, 10 deletions
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index 10f66b3f08..a5a437e099 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -31,6 +31,7 @@ import { SYSTEM_PREFERRED_LOCALE_KEY } from '../shared/gui-settings-state'; import { IpcMainEventChannel } from '../shared/ipc-event-channel'; import { backupLogFile, + cleanUpLogDirectory, getLogsDirectory, getMainLogFile, getRendererLogFile, @@ -264,6 +265,7 @@ class ApplicationMain { } } + cleanUpLogDirectory(); setupLogging(mainLogFile); } diff --git a/gui/src/shared/logging.ts b/gui/src/shared/logging.ts index c33f22a0b7..471fd758c8 100644 --- a/gui/src/shared/logging.ts +++ b/gui/src/shared/logging.ts @@ -28,7 +28,7 @@ export function getMainLogFile(): string { } export function getRendererLogFile(): string { - return path.join(getLogsDirectory(), 'frontend-renderer.log'); + return path.join(getLogsDirectory(), 'renderer.log'); } export function setupLogging(logFile: string) { @@ -48,18 +48,44 @@ export function setupLogging(logFile: string) { } } -export function backupLogFile(filePath: string): string | undefined { - const ext = path.extname(filePath); - const baseName = path.basename(filePath, ext); - const backupFile = path.join(path.dirname(filePath), baseName + '.old' + ext); +export function backupLogFile(filePath: string): boolean { + const exists = fileExists(filePath); + if (exists) { + const backupFilePath = getBackupFilePath(filePath); + fs.renameSync(filePath, backupFilePath); + } + + return exists; +} + +function getBackupFilePath(filePath: string): string { + const parsedPath = path.parse(filePath); + parsedPath.base = parsedPath.name + '.old' + parsedPath.ext; + return path.normalize(path.format(parsedPath)); +} +function fileExists(filePath: string): boolean { try { fs.accessSync(filePath); - fs.renameSync(filePath, backupFile); + return true; + } catch { + return false; + } +} + +// When cleaning up old log files they are first backed up and the next time removed. +export function cleanUpLogDirectory(): void { + const oldLogFileNames = ['frontend-renderer.log']; + + oldLogFileNames.forEach((fileName) => { + const filePath = path.join(getLogsDirectory(), fileName); + rotateOrDeleteFile(filePath); + }); +} - return backupFile; - } catch (error) { - // No previous log file exists - return undefined; +export function rotateOrDeleteFile(filePath: string) { + const backupFilePath = getBackupFilePath(filePath); + if (!backupLogFile(filePath) && fileExists(backupFilePath)) { + fs.unlinkSync(backupFilePath); } } diff --git a/gui/test/logging.spec.ts b/gui/test/logging.spec.ts new file mode 100644 index 0000000000..9572c6ed24 --- /dev/null +++ b/gui/test/logging.spec.ts @@ -0,0 +1,81 @@ +import { expect } from 'chai'; +import fs from 'fs'; +import sinon from 'sinon'; +import { it, describe, before, beforeEach, after } from 'mocha'; +import * as logging from '../src/shared/logging'; + +const aPath = 'log-directory/a.log'; +const oldAPath = 'log-directory/a.old.log'; +const bPath = 'log-directory/b.log'; +const oldBPath = 'log-directory/b.old.log'; + +const initialFileState = { + [aPath]: 'a', + [bPath]: 'b', + [oldBPath]: 'old b', +}; + +describe('Logging', () => { + let files: Record<string, string>; + let sandbox: sinon.SinonSandbox; + + before(() => { + sandbox = sinon.createSandbox(); + + sandbox.stub(fs, 'accessSync').callsFake((path) => { + if (files[path as string] === undefined) { + throw Error('File not found'); + } + }); + + sandbox.stub(fs, 'renameSync').callsFake((oldPath, newPath) => { + files[newPath as string] = files[oldPath as string]; + fs.unlinkSync(oldPath); + }); + + sandbox.stub(fs, 'unlinkSync').callsFake((path) => { + delete files[path as string]; + }); + + sandbox.stub(fs, 'readFileSync').callsFake((path) => { + return files[path as string] ?? ''; + }); + }); + + after(() => { + sandbox.restore(); + }); + + beforeEach(() => { + files = { ...initialFileState }; + }); + + it('should backup log file', () => { + logging.backupLogFile(aPath); + const oldA = fs.readFileSync(oldAPath).toString(); + + expect(fs.accessSync.bind(null, aPath)).to.throw(); + expect(oldA).to.equal(initialFileState[aPath]); + }); + + it('should replace backup file', () => { + logging.backupLogFile(bPath); + const oldB = fs.readFileSync(oldBPath).toString(); + + expect(fs.accessSync.bind(null, bPath)).to.throw(); + expect(oldB).to.equal(initialFileState[bPath]); + }); + + it('should clean up old log files', () => { + logging.rotateOrDeleteFile(bPath); + const oldB = fs.readFileSync(oldBPath).toString(); + + expect(fs.accessSync.bind(null, bPath)).to.throw(); + expect(oldB).to.equal(initialFileState[bPath]); + + logging.rotateOrDeleteFile(bPath); + + expect(fs.accessSync.bind(null, bPath)).to.throw(); + expect(fs.accessSync.bind(null, oldBPath)).to.throw(); + }); +}); |
