UNPKG

@syntest/core

Version:

The common core of the SynTest Framework

185 lines 8.75 kB
"use strict"; /* * Copyright 2020-2021 Delft University of Technology and SynTest contributors * * This file is part of SynTest Framework - SynTest Core. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SearchAlgorithm = void 0; const UserInterface_1 = require("../../ui/UserInterface"); /** * Abstract search algorithm to search for an optimal solution within the search space. * * The search algorithm is dependent on the encoding of the search space. * * @author Mitchell Olsthoorn */ class SearchAlgorithm { /** * Abstract constructor. * * @param eventManager The event manager * @param objectiveManager The objective manager * @protected */ constructor(eventManager, objectiveManager) { this._eventManager = eventManager; this._objectiveManager = objectiveManager; this._listeners = []; } /** * Search the search space for an optimal solution until one of the termination conditions are met. * * @param subject The subject of the search * @param budgetManager The budget manager to track budget progress * @param terminationManager The termination trigger manager */ search(subject, budgetManager, terminationManager) { return __awaiter(this, void 0, void 0, function* () { // Load search subject into the objective manager this._objectiveManager.load(subject); // Start initialization budget tracking budgetManager.initializationStarted(); (0, UserInterface_1.getUserInterface)().startProgressBar(); // Inform listeners that the search started this._listeners.forEach((listener) => { listener.searchStarted(this, budgetManager, terminationManager); }); (0, UserInterface_1.getUserInterface)().updateProgressBar(this.progress("branch"), budgetManager.getBudget()); this._eventManager.emitEvent("onSearchInitializationStart"); // Initialize search process yield this._initialize(budgetManager, terminationManager); // Stop initialization budget tracking, inform the listeners, and start search budget tracking budgetManager.initializationStopped(); this._eventManager.emitEvent("onSearchInitializationComplete"); this._listeners.forEach((listener) => listener.initializationDone(this, budgetManager, terminationManager)); (0, UserInterface_1.getUserInterface)().updateProgressBar(this.progress("branch"), budgetManager.getBudget()); budgetManager.searchStarted(); this._eventManager.emitEvent("onSearchStart"); // Start search until the budget has expired, a termination trigger has been triggered, or there are no more objectives while (this._objectiveManager.hasObjectives() && budgetManager.hasBudgetLeft() && !terminationManager.isTriggered()) { this._eventManager.emitEvent("onSearchIterationStart"); // Start next iteration of the search process yield this._iterate(budgetManager, terminationManager); // Inform the budget manager and listeners that an iteration happened budgetManager.iteration(this); this._eventManager.emitEvent("onSearchIterationComplete"); this._listeners.forEach((listener) => listener.iteration(this, budgetManager, terminationManager)); (0, UserInterface_1.getUserInterface)().updateProgressBar(this.progress("branch"), budgetManager.getBudget()); } // Stop search budget tracking budgetManager.searchStopped(); (0, UserInterface_1.getUserInterface)().stopProgressBar(); this._eventManager.emitEvent("onSearchComplete"); // Inform listeners that the search stopped this._listeners.forEach((listener) => { listener.searchStarted(this, budgetManager, terminationManager); }); // Return the archive of covered objectives return this._objectiveManager.getArchive(); }); } /** * Return the objective manager. */ getObjectiveManager() { return this._objectiveManager; } getCovered(objectiveType = "mixed") { const total = new Set(); const covered = new Set(); for (const key of this._objectiveManager.getArchive().getObjectives()) { const test = this._objectiveManager.getArchive().getEncoding(key); const result = test.getExecutionResult(); // TODO this does not work when there are files with the same name in different directories!! const paths = key.getSubject().path.split("/"); const fileName = paths[paths.length - 1]; result .getTraces() .filter((element) => element.type.includes(objectiveType) || objectiveType === "mixed") .filter((element) => element.path.includes(fileName)) .forEach((current) => { total.add(current.id + "_" + current.branchType); if (current.hits > 0) covered.add(current.id + "_" + current.branchType); }); } return covered.size; } getUncovered(objectiveType = "mixed") { const total = new Set(); const covered = new Set(); for (const key of this._objectiveManager.getArchive().getObjectives()) { const test = this._objectiveManager.getArchive().getEncoding(key); const result = test.getExecutionResult(); // TODO this does not work when there are files with the same name in different directories!! const paths = key.getSubject().path.split("/"); const fileName = paths[paths.length - 1]; result .getTraces() .filter((element) => element.type.includes(objectiveType) || objectiveType === "mixed") .filter((element) => element.path.includes(fileName)) .forEach((current) => { total.add(current.id + "_" + current.branchType); if (current.hits > 0) covered.add(current.id + "_" + current.branchType); }); } return total.size - covered.size; } /** * The progress of the search process. */ progress(objectiveType = "mixed") { const numberOfCoveredObjectives = this.getCovered(objectiveType); const numberOfUncoveredObjectives = this.getUncovered(objectiveType); const progress = (numberOfCoveredObjectives / (numberOfCoveredObjectives + numberOfUncoveredObjectives)) * 100; const factor = Math.pow(10, 2); return Math.round(progress * factor) / factor; } /** * Add a search listener to monitor the search process. * * @param listener The listener to add */ addListener(listener) { this._listeners.push(listener); return this; } /** * Remove a search listener from the search process. * * @param listener The listener to remove */ removeListener(listener) { this._listeners.slice(this._listeners.indexOf(listener), 1); return this; } } exports.SearchAlgorithm = SearchAlgorithm; //# sourceMappingURL=SearchAlgorithm.js.map