[RM] Feature [SF][BB] Parallel upload matrices into slave.
MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/bigbutton/execution/ExecutorClient.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/bigbutton/execution/ExecutorClient.java
@@ -27,6 +27,7 @@ import com.exactpro.sf.bigbutton.library.Globals;
import com.exactpro.sf.bigbutton.library.IBBActionExecutor;
import com.exactpro.sf.bigbutton.library.Library;
import com.exactpro.sf.bigbutton.library.Script;
+import com.exactpro.sf.bigbutton.library.Script.ScriptRemoteInformation;
import com.exactpro.sf.bigbutton.library.ScriptList;
import com.exactpro.sf.bigbutton.library.ScriptList.ScriptListStatus;
import com.exactpro.sf.bigbutton.library.Service;
@@ -369,6 +370,9 @@ public class ExecutorClient {
} catch (RuntimeException e) {
toErrorState(e);
}
+
+ stopRunningTestScripts();
+
}
public void registerTags(List<Tag> tags) {
@@ -536,8 +540,92 @@ public class ExecutorClient {
}
- private void executeScript(Script script) throws InterruptedException {
+
+ private XmlTestScriptShortReport waitForScriptExecutionFinish(Script script, int id) throws InterruptedException {
+
+ logger.debug("Got id {}. Monitoring status...", id);
+
+ ScriptExecutionStatistics statistics = script.getStatistics();
+
+ while(true) {
+
+ try {
+
+ if(!running) {
+ logger.info("Invoking stop");
+ apiClient.stopTestScriptRun(id);
+ return null;
+ }
+
+ Thread.sleep(1000);
+
+ XmlTestScriptShortReport response = apiClient.getTestScriptRunShortReport(id);
+
+ if(response != null) {
+ logger.debug("Status: {}", response);
+ }
+
+ statistics.setNumPassed(response.getPassed());
+ statistics.setNumConditionallyPassed(response.getConditionallyPassed());
+ statistics.setNumFailed(response.getFailed());
+
+ statistics.setStatus(response.getStatus());
+
+ if (!response.isLocked()) {
+
+ script.setFinished(true);
+
+ script.setCause(TestScriptDescription.getCauseMessage(response.getCause()));
+
+ statistics.setTotal(response.getTotal());
+
+ return response;
+
+ }
+
+ } catch (InterruptedException e) {
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ throw new RuntimeException("Could not perform status check call", e); // TODO: replace with checked exception
+
+ }
+
+ }
+
+ }
+
+ private void executeOnFinish(StatusType statusType, Set<BigButtonAction> actionsToExecute, String subSubject, IBBActionExecutor... parameters) {
+ logger.info("executeOnFinish was triggered");
+ for (BigButtonAction action : actionsToExecute) {
+ try {
+ actions.get(action).accept(statusType, subSubject, parameters);
+ } catch (Exception e) {
+ logger.error("Exception during BBAction execute", e.getMessage());
+ }
+ }
+ }
+
+ private void executeOnFinishScript(Script script){
+ logger.info("executeOnFinishScript was triggered");
+ StatusType statusType = script.getStatusType();
+ executeOnFinish(statusType, script.getActions(), StringUtils.join("Script ", statusType.name().toLowerCase()), currentList, script);
+ }
+
+
+ private void executeOnFinishScriptList(ScriptList scriptList){
+ logger.info("executeOnFinishScriptList was triggered");
+ StatusType statusType = scriptList.getStatusType();
+ executeOnFinish(statusType, scriptList.getActions(), StringUtils.join("Script list ", statusType.name().toLowerCase()), scriptList);
+ }
+
+ /**
+ * Upload and start compile script on slave
+ * @param script
+ * @throws InterruptedException
+ */
+ private void compileScript(Script script) throws InterruptedException {
//SfApiOptions scriptOptions = script.getApiOptions();
SfApiOptions scriptOptions = library.getDefaultApiOptions();
@@ -587,7 +675,7 @@ public class ExecutorClient {
0, // aml version is deprecated
scriptOptions.getContinueIfFailed(),
scriptOptions.getAutoStart(),
- true,
+ false,
scriptOptions.getIgnoreAskForContinue(),
scriptOptions.getRunNetDumper(),
scriptOptions.getSkipOptional(),
@@ -596,8 +684,54 @@ public class ExecutorClient {
targetReportFolder,
scriptOptions.getLanguage());
- long scriptRunId = response.getId();
+ apiClient.compileTestScriptRun((int) response.getId());
+ script.setRemoteInformation(new ScriptRemoteInformation(response.getId(), matrix.getId()));
+ }
+ }
+ catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ throw new RuntimeException("Could not perform api call", e); // TODO: replace with checked exception
+
+ }
+ }
+
+ /**
+ * Wait while script will be compiled
+ * @param testScriptId
+ * @throws InterruptedException
+ */
+ private void waitForCompileTestScript(int testScriptId) throws InterruptedException{
+ try {
+ while (!"READY".equals(apiClient.getTestScriptRunInfo(testScriptId).getScriptState())) {
+ Thread.sleep(1000);
+ }
+ } catch (APICallException | APIResponseException e) {
+ throw new EPSCommonException("Could not get scripts state for test script with id + {" + testScriptId + '}', e);
+ }
+ }
+ /**
+ * Send request to slave to start script
+ * @param testScriptId
+ * @throws InterruptedException
+ */
+ private void startScript(int testScriptId) throws InterruptedException {
+ try {
+ apiClient.runCompiledTestScript(testScriptId);
+ } catch (APICallException | APIResponseException e) {
+ throw new EPSCommonException("Can`t start test script with id [" + testScriptId + ']', e);
+ }
+ }
+
+ /**
+ * Wait while script will be executed, then update statistic and download report
+ * @param script
+ * @param scriptRunId
+ * @param matrixId
+ * @throws InterruptedException
+ */
+ private void waitForExecutingTestScriptAndCollectStatisticAndReport(Script script, long scriptRunId, long matrixId) throws InterruptedException {
+ try {
XmlTestScriptShortReport executionResult = waitForScriptExecutionFinish(script, (int)scriptRunId);
ListExecutionStatistics statistics = currentList.getExecutionStatistics();
@@ -612,7 +746,6 @@ public class ExecutorClient {
statistics.incNumConditionallyPassed();
-
} else {
statistics.incNumPassed();
@@ -629,100 +762,37 @@ public class ExecutorClient {
reportDownloadNeeded = true;
}
-
executeOnFinishScript(script);
monitor.scriptExecuted(script, (int)scriptRunId, executor, relativeListReportsFolder, reportDownloadNeeded);
- apiClient.deleteMatrix((int)matrix.getId());
- }
-
- }catch (InterruptedException e){
- throw e;
- }
- catch (Exception e) {
+ apiClient.deleteMatrix((int)matrixId);
+ } catch (Exception e) {
logger.error(e.getMessage(), e);
throw new RuntimeException("Could not perform api call", e); // TODO: replace with checked exception
-
}
-
}
- private XmlTestScriptShortReport waitForScriptExecutionFinish(Script script, int id) throws InterruptedException {
-
- logger.debug("Got id {}. Monitoring status...", id);
-
- ScriptExecutionStatistics statistics = script.getStatistics();
-
- while(true) {
-
- try {
-
+ /**
+ * Check BB is not running, or wait if BB is on pause
+ * @return True - if BB is not running, False - if BB is running
+ * @throws InterruptedException
+ */
+ private boolean checkIsNotRun() throws InterruptedException {
if (!running) {
- logger.info("Invoking stop");
- apiClient.stopTestScriptRun(id);
- return null;
- }
-
- Thread.sleep(1000);
-
- XmlTestScriptShortReport response = apiClient.getTestScriptRunShortReport(id);
-
- if(response != null) {
- logger.debug("Status: {}", response);
- }
-
- statistics.setNumPassed(response.getPassed());
- statistics.setNumConditionallyPassed(response.getConditionallyPassed());
- statistics.setNumFailed(response.getFailed());
-
- statistics.setStatus(response.getStatus());
-
- if (!response.isLocked()) {
-
- script.setFinished(true);
-
- script.setCause(TestScriptDescription.getCauseMessage(response.getCause()));
-
- statistics.setTotal(response.getTotal());
-
- return response;
-
- }
-
- } catch (InterruptedException e) {
- throw e;
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- throw new RuntimeException("Could not perform status check call", e); // TODO: replace with checked exception
-
- }
-
+ return true;
}
- }
+ if (runner.isPause()) {
+ state = ExecutorState.Paused;
- private void executeOnFinish(StatusType statusType, Set<BigButtonAction> actionsToExecute, String subSubject, IBBActionExecutor... parameters) {
- logger.info("executeOnFinish was triggered");
- for (BigButtonAction action : actionsToExecute) {
- try {
- actions.get(action).accept(statusType, subSubject, parameters);
- } catch (Exception e) {
- logger.error("Exception during BBAction execute", e.getMessage());
- }
- }
+ while (runner.isPause()) {
+ Thread.sleep(1000);
}
- private void executeOnFinishScript(Script script){
- logger.info("executeOnFinishScript was triggered");
- StatusType statusType = script.getStatusType();
- executeOnFinish(statusType, script.getActions(), StringUtils.join("Script ", statusType.name().toLowerCase()), currentList, script);
+ state = ExecutorState.Executing;
}
-
- private void executeOnFinishScriptList(ScriptList scriptList){
- logger.info("executeOnFinishScriptList was triggered");
- StatusType statusType = scriptList.getStatusType();
- executeOnFinish(statusType, scriptList.getActions(), StringUtils.join("Script list ", statusType.name().toLowerCase()), scriptList);
+ return false;
}
private void runList() throws InterruptedException {
@@ -734,29 +804,32 @@ public class ExecutorClient {
this.relativeListReportsFolder = createRelativeListRepotsFolder();
- for(int i =0; i< currentList.getScripts().size(); i++) {//Script script : currentList.getScripts()) {
+ for (int i = 0; i < currentList.getScripts().size(); i++) {
- if(!running) {
+ if (checkIsNotRun()){
return;
}
- if(runner.isPause()){
- state = ExecutorState.Paused;
-
- while (runner.isPause()) {
- Thread.sleep(1000);
+ compileScript(currentList.getScripts().get(i));
}
- state = ExecutorState.Executing;
- }
+ for(int i =0; i < currentList.getScripts().size(); i++) {//Script script : currentList.getScripts()) {
+ if (checkIsNotRun()){
+ return;
+ }
Script script = currentList.getScripts().get(i);
currentList.setCurrentScript(script);
- if (!currentList.getStatus().isSkipped()) {
- executeScript(script);
+ if (!currentList.getStatus().isSkipped() && script.getRemoteInformation() != null) {
+
+ waitForCompileTestScript((int) script.getRemoteInformation().getTestScriptId());
+
+ startScript((int) script.getRemoteInformation().getTestScriptId());
+
+ waitForExecutingTestScriptAndCollectStatisticAndReport(script, script.getRemoteInformation().getTestScriptId(), script.getRemoteInformation().getMatrixId());
} else {
script.getStatistics().setStatus("SKIPPED");
script.setFinished(true);
@@ -770,7 +843,6 @@ public class ExecutorClient {
statistics.setExecutionPercent(
RegressionRunnerUtils.calcPercent(i + 1, currentList.getScripts().size()));
-
}
} catch (InterruptedException e){
@@ -1075,4 +1147,29 @@ public class ExecutorClient {
}
}
+ private void stopRunningTestScripts() {
+ try {
+ // currentList may be null when BB end to running all test scripts.
+ // When BB execute action Interrupt currentList is not null
+ if (currentList != null) {
+ currentList
+ .getScripts()
+ .stream()
+ .filter(script -> !script.isFinished())
+ .forEach(script -> {
+ try {
+ apiClient.stopTestScriptRun((int)script.getRemoteInformation().getTestScriptId());
+ apiClient.deleteTestScriptRun((int) script.getRemoteInformation().getTestScriptId());
+ apiClient.deleteMatrix((int)script.getRemoteInformation().getMatrixId());
+ } catch (APICallException | APIResponseException e) {
+ throw new EPSCommonException("Could not perform api call", e);
+ }
+ });
+ }
+ } catch (RuntimeException e){
+ toErrorState(e);
+ }
+ }
+
+
}

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/bigbutton/library/Script.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/bigbutton/library/Script.java
@@ -53,6 +53,33 @@ public class Script implements Serializable, IBBActionExecutor {
private String cause;
+ private ScriptRemoteInformation remoteInformation = null;
+
+ public static class ScriptRemoteInformation {
+ private long testScriptId;
+ private long matrixId;
+
+ public ScriptRemoteInformation(long testScriptId, long matrixId) {
+ this.testScriptId = testScriptId;
+ this.matrixId = matrixId;
+ }
+
+ public long getTestScriptId() {
+ return testScriptId;
+ }
+
+ public void setTestScriptId(long testScriptId) {
+ this.testScriptId = testScriptId;
+ }
+
+ public long getMatrixId() {
+ return matrixId;
+ }
+
+ public void setMatrixId(long matrixId) {
+ this.matrixId = matrixId;
+ }
+ }
public Script(long lineNumber){
this.lineNumber = lineNumber;
@@ -153,6 +180,14 @@ public class Script implements Serializable, IBBActionExecutor {
this.cause = cause;
}
+ public ScriptRemoteInformation getRemoteInformation() {
+ return remoteInformation;
+ }
+
+ public void setRemoteInformation(ScriptRemoteInformation remoteInformation) {
+ this.remoteInformation = remoteInformation;
+ }
+
@Override
@SuppressWarnings("incomplete-switch")
public Set<BigButtonAction> getActions() {

MODIFY
BackEnd/Core/sailfish-core/src/main/workspace/cfg/sf.cfg.xml
BackEnd/Core/sailfish-core/src/main/workspace/cfg/sf.cfg.xml
<NotificationIfSomeServicesNotStarted>false</NotificationIfSomeServicesNotStarted>
<FailUnexpected>false</FailUnexpected>
<!-- Priority of the matrices compilation thread, values [1, 10] -->
- <MatrixCompilerPriority>5</MatrixCompilerPriority>
+ <MatrixCompilerPriority>1</MatrixCompilerPriority>
<!-- Format of report creation: zip - remove files after archiving; files - disable auto-archive; zip_files - do not remove files, enable auto-archive -->
<ReportOutputFormat>zip_files</ReportOutputFormat>
<!-- Set of excluded messages from information block about all messages in report. Property may have several values separated by comma character -->

[RM] Feature #59799. [SF][BB] Parallel upload matrices into slave.

Change-Id: If866a6ba5fc9a9897e0b1a3615451370b5269770