forked from DevExpress/testcafe
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reduce number of created temp dirs for profiles (closes DevExpress#2735…
…, closes DevExpress#2013) (DevExpress#2740) * Reduce number of created temp dirs for profiles (closes DevExpress#2735) * Add test * Remove temp dirs in a separate process * Fix tests * Fix remarks
- Loading branch information
1 parent
c6b6145
commit 36527ff
Showing
17 changed files
with
540 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { spawn } from 'child_process'; | ||
import OS from 'os-family'; | ||
import promisifyEvent from 'promisify-event'; | ||
import Promise from 'pinkie'; | ||
import { findProcess, killProcess } from './promisified-functions'; | ||
|
||
|
||
const BROWSER_CLOSING_TIMEOUT = 5; | ||
|
||
async function runWMIC (args) { | ||
const wmicProcess = spawn('wmic.exe', args, { detached: true }); | ||
|
||
let wmicOutput = ''; | ||
|
||
wmicProcess.stdout.on('data', data => { | ||
wmicOutput += data.toString(); | ||
}); | ||
|
||
try { | ||
await Promise.race([ | ||
promisifyEvent(wmicProcess.stdout, 'end'), | ||
promisifyEvent(wmicProcess, 'error') | ||
]); | ||
|
||
return wmicOutput; | ||
} | ||
catch (e) { | ||
return ''; | ||
} | ||
} | ||
|
||
async function findProcessWin (processOptions) { | ||
var wmicArgs = ['process', 'where', `commandline like '%${processOptions.arguments}%' and name <> 'cmd.exe' and name <> 'wmic.exe'`, 'get', 'processid']; | ||
var wmicOutput = await runWMIC(wmicArgs); | ||
var processList = wmicOutput.split(/\s*\n/); | ||
|
||
processList = processList | ||
// NOTE: remove list's header and empty last element, caused by trailing newline | ||
.slice(1, -1) | ||
.map(pid => ({ pid: Number(pid) })); | ||
|
||
return processList; | ||
} | ||
|
||
export default async function (browserId) { | ||
var processOptions = { arguments: browserId, psargs: '-ef' }; | ||
var processList = OS.win ? await findProcessWin(processOptions) : await findProcess(processOptions); | ||
|
||
if (!processList.length) | ||
return true; | ||
|
||
try { | ||
if (OS.win) | ||
process.kill(processList[0].pid); | ||
else | ||
await killProcess(processList[0].pid, { timeout: BROWSER_CLOSING_TIMEOUT }); | ||
|
||
return true; | ||
} | ||
catch (e) { | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export default { | ||
init: 'init', | ||
add: 'add', | ||
remove: 'remove' | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import { spawn } from 'child_process'; | ||
import debug from 'debug'; | ||
import promisifyEvent from 'promisify-event'; | ||
import Promise from 'pinkie'; | ||
import { sendMessageToChildProcess } from '../../promisified-functions'; | ||
import COMMANDS from './commands'; | ||
|
||
|
||
const WORKER_PATH = require.resolve('./worker'); | ||
const WORKER_STDIO_CONFIG = ['ignore', 'ignore', 'ignore', 'ipc']; | ||
|
||
const DEBUG_LOGGER = debug('testcafe:utils:temp-directory:cleanup-process'); | ||
|
||
class CleanupProcess { | ||
constructor () { | ||
this.worker = null; | ||
this.initialized = false; | ||
this.initPromise = Promise.resolve(void 0); | ||
|
||
this.messageCounter = 0; | ||
|
||
this.pendingResponses = {}; | ||
} | ||
|
||
_sendMessage (id, msg) { | ||
return sendMessageToChildProcess(this.worker, { id, ...msg }); | ||
} | ||
|
||
_onResponse (response) { | ||
const pendingResponse = this.pendingResponses[response.id]; | ||
|
||
if (response.error) { | ||
if (pendingResponse) | ||
pendingResponse.control.reject(response.error); | ||
else | ||
this.pendingResponses[response.id] = Promise.reject(response.error); | ||
} | ||
else if (pendingResponse) | ||
pendingResponse.control.resolve(); | ||
else | ||
this.pendingResponses[response.id] = Promise.resolve(); | ||
} | ||
|
||
async _waitResponse (id) { | ||
if (!this.pendingResponses[id]) { | ||
const promiseControl = {}; | ||
|
||
this.pendingResponses[id] = new Promise((resolve, reject) => { | ||
Object.assign(promiseControl, { resolve, reject }); | ||
}); | ||
|
||
this.pendingResponses[id].control = promiseControl; | ||
} | ||
|
||
try { | ||
await this.pendingResponses[id]; | ||
} | ||
finally { | ||
delete this.pendingResponses[id]; | ||
} | ||
} | ||
|
||
async _waitResponseForMessage (msg) { | ||
const currentId = this.messageCounter; | ||
|
||
this.messageCounter++; | ||
|
||
await this._sendMessage(currentId, msg); | ||
await this._waitResponse(currentId); | ||
} | ||
|
||
init () { | ||
this.initPromise = this.initPromise | ||
.then(async initialized => { | ||
if (initialized !== void 0) | ||
return initialized; | ||
|
||
this.worker = spawn(process.argv[0], [WORKER_PATH], { detached: true, stdio: WORKER_STDIO_CONFIG }); | ||
|
||
this.worker.on('message', message => this._onResponse(message)); | ||
|
||
this.worker.unref(); | ||
|
||
try { | ||
await Promise.race([ | ||
this._waitResponseForMessage({ command: COMMANDS.init }), | ||
promisifyEvent(this.worker, 'error') | ||
]); | ||
|
||
const channel = this.worker.channel || this.worker._channel; | ||
|
||
channel.unref(); | ||
|
||
this.initialized = true; | ||
} | ||
catch (e) { | ||
DEBUG_LOGGER('Failed to start cleanup process'); | ||
DEBUG_LOGGER(e); | ||
|
||
this.initialized = false; | ||
} | ||
|
||
return this.initialized; | ||
}); | ||
|
||
return this.initPromise; | ||
} | ||
|
||
async addDirectory (path) { | ||
if (!this.initialized) | ||
return; | ||
|
||
try { | ||
await this._waitResponseForMessage({ command: COMMANDS.add, path }); | ||
} | ||
catch (e) { | ||
DEBUG_LOGGER(`Failed to add the ${path} directory to cleanup process`); | ||
DEBUG_LOGGER(e); | ||
} | ||
} | ||
|
||
async removeDirectory (path) { | ||
if (!this.initialized) | ||
return; | ||
|
||
try { | ||
await this._waitResponseForMessage({ command: COMMANDS.remove, path }); | ||
} | ||
catch (e) { | ||
DEBUG_LOGGER(`Failed to remove the ${path} directory in cleanup process`); | ||
DEBUG_LOGGER(e); | ||
} | ||
} | ||
} | ||
|
||
export default new CleanupProcess(); |
Oops, something went wrong.