appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
147 lines • 6.33 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.markSystemFilesForCleanup = markSystemFilesForCleanup;
exports.clearSystemFiles = clearSystemFiles;
exports.cleanup = cleanup;
const support_1 = require("appium/support");
const utils_1 = require("../../utils");
const node_os_1 = __importDefault(require("node:os"));
const node_path_1 = __importDefault(require("node:path"));
const teen_process_1 = require("teen_process");
const logger_1 = require("../../logger");
const constants_1 = require("./constants");
const XCTEST_LOG_FILES_PATTERNS = [
/^Session-WebDriverAgentRunner.*\.log$/i,
/^StandardOutputAndStandardError\.txt$/i,
];
const XCTEST_LOGS_CACHE_FOLDER_PREFIX = 'com.apple.dt.XCTest';
// This map contains derived data logs folders as keys
// and values are the count of times the particular
// folder has been scheduled for removal
const derivedDataCleanupMarkers = new Map();
/** Marks WDA logs folder for deferred cleanup across parallel sessions. */
async function markSystemFilesForCleanup(retrieveDerivedDataPath) {
const derivedDataPath = await retrieveDerivedDataPath();
if (!derivedDataPath) {
logger_1.log.warn('No WebDriverAgent derived data available, so unable to mark system files for cleanup');
return;
}
const logsRoot = node_path_1.default.resolve(derivedDataPath, 'Logs');
const markersCount = derivedDataCleanupMarkers.get(logsRoot) ?? 0;
derivedDataCleanupMarkers.set(logsRoot, markersCount + 1);
}
/** Cleans per-session WDA logs and stale XCTest temporary logs. */
async function clearSystemFiles(retrieveDerivedDataPath) {
const derivedDataPath = await retrieveDerivedDataPath();
if (!derivedDataPath) {
logger_1.log.warn('No WebDriverAgent derived data available, so unable to clear system files');
return;
}
const logsRoot = node_path_1.default.resolve(derivedDataPath, 'Logs');
const existingCount = derivedDataCleanupMarkers.get(logsRoot);
if (existingCount !== undefined) {
let markersCount = existingCount;
derivedDataCleanupMarkers.set(logsRoot, --markersCount);
if (markersCount > 0) {
logger_1.log.info(`Not cleaning '${logsRoot}' folder, because the other session does not expect it to be cleaned`);
return;
}
}
derivedDataCleanupMarkers.set(logsRoot, 0);
// Cleaning up big temporary files created by XCTest: https://github.com/appium/appium/issues/9410
const globPattern = `${node_os_1.default.tmpdir()}/${XCTEST_LOGS_CACHE_FOLDER_PREFIX}*/`;
const dstFolders = await support_1.fs.glob(globPattern);
if ((0, utils_1.isEmpty)(dstFolders)) {
logger_1.log.debug(`Did not find the temporary XCTest logs root at '${globPattern}'`);
}
else {
const promises = [];
for (const dstFolder of dstFolders) {
const promise = (async () => {
const deletionPromises = [];
try {
await support_1.fs.walkDir(dstFolder, true, (itemPath, isDir) => {
if (isDir) {
return;
}
const fileName = node_path_1.default.basename(itemPath);
if (XCTEST_LOG_FILES_PATTERNS.some((p) => p.test(fileName))) {
deletionPromises.push(support_1.fs.rimraf(itemPath));
}
});
if (deletionPromises.length) {
await Promise.all(deletionPromises);
}
}
catch (e) {
logger_1.log.debug(e.stack);
logger_1.log.info(e.message);
}
})();
promises.push(promise);
}
logger_1.log.debug(`Started XCTest logs cleanup in '${dstFolders}'`);
if (promises.length) {
await Promise.all(promises);
}
}
if (await support_1.fs.exists(logsRoot)) {
logger_1.log.info(`Cleaning test logs in '${logsRoot}' folder`);
await clearLogs([logsRoot]);
return;
}
logger_1.log.info(`There is no ${logsRoot} folder, so not cleaning files`);
}
/**
* Clears WebDriverAgent system files after session teardown when enabled via capability.
*/
async function cleanup(driver) {
if (!driver._wda || !(0, constants_1.isXcodebuildNeeded)(driver.opts)) {
return;
}
if (!driver.opts.clearSystemFiles) {
driver.log.debug('Not clearing log files. Use `clearSystemFiles` capability to turn on.');
return;
}
let synchronizationKey = constants_1.XCUITEST_DRIVER_SYNC_NAME;
const derivedDataPath = await driver.wda.retrieveDerivedDataPath();
if (derivedDataPath) {
synchronizationKey = node_path_1.default.normalize(derivedDataPath);
}
await constants_1.SHARED_RESOURCES_GUARD.acquire(synchronizationKey, async () => {
await clearSystemFiles(() => driver.wda.retrieveDerivedDataPath());
});
}
/** Deletes the provided filesystem locations, logging reclaimed size when available. */
async function clearLogs(locations) {
logger_1.log.debug('Clearing log files');
const cleanupPromises = [];
for (const location of locations) {
if (!(await support_1.fs.exists(location))) {
continue;
}
cleanupPromises.push((async () => {
let size;
try {
const { stdout } = await (0, teen_process_1.exec)('du', ['-sh', location]);
size = stdout.trim().split(/\s+/)[0];
}
catch { }
try {
logger_1.log.debug(`Deleting '${location}'. ${size ? `Freeing ${size}.` : ''}`);
await support_1.fs.rimraf(location);
}
catch (err) {
logger_1.log.warn(`Unable to delete '${location}': ${err.message}`);
}
})());
}
if (!(0, utils_1.isEmpty)(cleanupPromises)) {
await Promise.all(cleanupPromises);
}
logger_1.log.debug('Finished clearing log files');
}
//# sourceMappingURL=cleanup.js.map