refactor(接口测试): 优化误报逻辑
--story=1011259 --user=王孝刚 【Bug转需求】误报机制和失败重试机制冲突导致问题“【测试跟踪】测试计划失败重试,所有的接口 / 场景步骤 都重试了“ https://www.tapd.cn/55049933/s/1344889
This commit is contained in:
parent
1db32ded82
commit
5561193ae9
|
@ -11,12 +11,12 @@ import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class ErrorReportLibraryParseDTO {
|
public class FakeErrorLibraryDTO {
|
||||||
private List<String> errorCodeList;
|
private List<String> errorCodeList;
|
||||||
private RequestResult result;
|
private RequestResult result;
|
||||||
private String requestStatus;
|
private String requestStatus;
|
||||||
|
|
||||||
public ErrorReportLibraryParseDTO() {
|
public FakeErrorLibraryDTO() {
|
||||||
this.errorCodeList = new ArrayList<>();
|
this.errorCodeList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.metersphere.api.dto.definition;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FakeError {
|
||||||
|
private String projectId;
|
||||||
|
private boolean higherThanSuccess;
|
||||||
|
private boolean higherThanError;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.metersphere.api.dto.definition;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class MsRegexDTO {
|
||||||
|
private String subject;
|
||||||
|
private String condition;
|
||||||
|
private String value;
|
||||||
|
private String errorCode;
|
||||||
|
private boolean pass;
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ import io.metersphere.api.dto.definition.request.assertions.document.MsAssertion
|
||||||
import io.metersphere.commons.constants.ElementConstants;
|
import io.metersphere.commons.constants.ElementConstants;
|
||||||
import io.metersphere.commons.constants.PropertyConstant;
|
import io.metersphere.commons.constants.PropertyConstant;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.commons.utils.ErrorReportLibraryUtil;
|
|
||||||
import io.metersphere.plugin.core.MsParameter;
|
import io.metersphere.plugin.core.MsParameter;
|
||||||
import io.metersphere.plugin.core.MsTestElement;
|
import io.metersphere.plugin.core.MsTestElement;
|
||||||
import io.metersphere.service.definition.ApiDefinitionService;
|
import io.metersphere.service.definition.ApiDefinitionService;
|
||||||
|
@ -105,24 +104,19 @@ public class MsAssertions extends MsTestElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResponseAssertion responseAssertion(MsAssertionRegex assertionRegex) {
|
private ResponseAssertion responseAssertion(MsAssertionRegex assertionRegex) {
|
||||||
ResponseAssertion assertion = null;
|
ResponseAssertion assertion = new ResponseAssertion();
|
||||||
boolean isErrorReportAssertion = false;
|
assertion.setEnabled(this.isEnable());
|
||||||
if (StringUtils.startsWith(this.getName(), "ErrorReportAssertion:")) {
|
if (StringUtils.isNotEmpty(assertionRegex.getDescription())) {
|
||||||
assertion = new ErrorReportAssertion();
|
assertion.setName(StringUtils.join(this.getName(), delimiter, assertionRegex.getDescription()));
|
||||||
isErrorReportAssertion = true;
|
|
||||||
} else {
|
} else {
|
||||||
assertion = new ResponseAssertion();
|
assertion.setName(StringUtils.join(this.getName(), delimiter, "AssertionRegex"));
|
||||||
}
|
}
|
||||||
assertion.setEnabled(this.isEnable());
|
assertion.setEnabled(this.isEnable());
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(assertionRegex.getDescription())) {
|
if (StringUtils.isNotEmpty(assertionRegex.getDescription())) {
|
||||||
if (!isErrorReportAssertion) {
|
assertion.setName(StringUtils.join(this.getName(), delimiter, assertionRegex.getDescription()));
|
||||||
//正常断言要在desc增加匹配信息,用于接受结果后和误报断言进行匹配
|
|
||||||
assertionRegex.setDescription(assertionRegex.getDescription() + ErrorReportLibraryUtil.ASSERTION_CONTENT_REGEX_DELIMITER + assertionRegex.getSubject() + ":" + assertionRegex.getExpression());
|
|
||||||
}
|
|
||||||
assertion.setName(this.getName() + delimiter + assertionRegex.getDescription());
|
|
||||||
} else {
|
} else {
|
||||||
assertion.setName(this.getName() + delimiter + "AssertionRegex" + ErrorReportLibraryUtil.ASSERTION_CONTENT_REGEX_DELIMITER + assertionRegex.getSubject() + ":" + assertionRegex.getExpression());
|
assertion.setName(StringUtils.join(this.getName(), delimiter, "AssertionRegex"));
|
||||||
}
|
}
|
||||||
assertion.setProperty(TestElement.TEST_CLASS, ResponseAssertion.class.getName());
|
assertion.setProperty(TestElement.TEST_CLASS, ResponseAssertion.class.getName());
|
||||||
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("AssertionGui"));
|
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("AssertionGui"));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.api.dto.definition.request.sampler;
|
package io.metersphere.api.dto.definition.request.sampler;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.definition.FakeError;
|
||||||
import io.metersphere.api.dto.definition.request.ElementUtil;
|
import io.metersphere.api.dto.definition.request.ElementUtil;
|
||||||
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
||||||
|
@ -31,12 +32,14 @@ import io.metersphere.service.definition.ApiTestCaseService;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.config.Arguments;
|
import org.apache.jmeter.config.Arguments;
|
||||||
import org.apache.jmeter.config.KeystoreConfig;
|
import org.apache.jmeter.config.KeystoreConfig;
|
||||||
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
import org.apache.jmeter.protocol.http.util.HTTPArgument;
|
import org.apache.jmeter.protocol.http.util.HTTPArgument;
|
||||||
import org.apache.jmeter.protocol.http.util.HTTPConstants;
|
import org.apache.jmeter.protocol.http.util.HTTPConstants;
|
||||||
|
import org.apache.jmeter.samplers.SampleResult;
|
||||||
import org.apache.jmeter.save.SaveService;
|
import org.apache.jmeter.save.SaveService;
|
||||||
import org.apache.jmeter.testelement.TestElement;
|
import org.apache.jmeter.testelement.TestElement;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
@ -213,10 +216,8 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
//根据配置增加全局前后至脚本
|
//根据配置增加全局前后至脚本
|
||||||
JMeterScriptUtil.setScriptByHttpConfig(httpConfig, httpSamplerTree, config, useEnvironment, this.getEnvironmentId(), false);
|
JMeterScriptUtil.setScriptByHttpConfig(httpConfig, httpSamplerTree, config, useEnvironment, this.getEnvironmentId(), false);
|
||||||
//增加误报、断言
|
//增加误报、断言
|
||||||
if (!config.isOperating() && CollectionUtils.isNotEmpty(httpConfig.getErrorReportAssertions())) {
|
if (ObjectUtils.isNotEmpty(httpConfig.getFakeError())) {
|
||||||
for (MsAssertions assertion : httpConfig.getErrorReportAssertions()) {
|
sampler.setProperty(SampleResult.MS_FAKE_ERROR, JSONUtil.toJSONString(httpConfig.getFakeError()));
|
||||||
assertion.toHashTree(httpSamplerTree, assertion.getHashTree(), config);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(httpConfig.getAssertions())) {
|
if (CollectionUtils.isNotEmpty(httpConfig.getAssertions())) {
|
||||||
for (MsAssertions assertion : httpConfig.getAssertions()) {
|
for (MsAssertions assertion : httpConfig.getAssertions()) {
|
||||||
|
@ -335,7 +336,11 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
httpConfig.setAssertions(ElementUtil.copyAssertion(environmentConfig.getAssertions()));
|
httpConfig.setAssertions(ElementUtil.copyAssertion(environmentConfig.getAssertions()));
|
||||||
}
|
}
|
||||||
if (environmentConfig.isUseErrorCode()) {
|
if (environmentConfig.isUseErrorCode()) {
|
||||||
httpConfig.setErrorReportAssertions(HashTreeUtil.getErrorReportByProjectId(this.getProjectId(), environmentConfig.isHigherThanSuccess(), environmentConfig.isHigherThanError()));
|
FakeError fakeError = new FakeError();
|
||||||
|
fakeError.setHigherThanError(environmentConfig.isHigherThanError());
|
||||||
|
fakeError.setProjectId(this.getProjectId());
|
||||||
|
fakeError.setHigherThanSuccess(environmentConfig.isHigherThanSuccess());
|
||||||
|
httpConfig.setFakeError(fakeError);
|
||||||
}
|
}
|
||||||
return httpConfig;
|
return httpConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
//添加csv
|
//添加csv
|
||||||
ElementUtil.addApiVariables(config, tree, this.getProjectId());
|
ElementUtil.addApiVariables(config, tree, this.getProjectId());
|
||||||
//增加误报、全局断言
|
//增加误报、全局断言
|
||||||
HashTreeUtil.addPositive(envConfig, samplerHashTree, config, this.getProjectId());
|
HashTreeUtil.addPositive(envConfig, samplerHashTree, config, this.getProjectId(), jdbcSampler);
|
||||||
//处理全局前后置脚本(步骤内)
|
//处理全局前后置脚本(步骤内)
|
||||||
String environmentId = this.getEnvironmentId();
|
String environmentId = this.getEnvironmentId();
|
||||||
if (environmentId == null) {
|
if (environmentId == null) {
|
||||||
|
|
|
@ -3,7 +3,6 @@ package io.metersphere.api.dto.definition.request.sampler;
|
||||||
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
||||||
import io.metersphere.api.dto.definition.request.ElementUtil;
|
import io.metersphere.api.dto.definition.request.ElementUtil;
|
||||||
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
|
||||||
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
||||||
import io.metersphere.api.dto.scenario.KeyValue;
|
import io.metersphere.api.dto.scenario.KeyValue;
|
||||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
|
@ -140,13 +139,14 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
ElementUtil.addApiVariables(config, tree, this.getProjectId());
|
ElementUtil.addApiVariables(config, tree, this.getProjectId());
|
||||||
final HashTree samplerHashTree = new ListedHashTree();
|
final HashTree samplerHashTree = new ListedHashTree();
|
||||||
samplerHashTree.add(tcpConfig());
|
samplerHashTree.add(tcpConfig());
|
||||||
tree.set(tcpSampler(config), samplerHashTree);
|
TCPSampler tcpSampler = tcpSampler(config);
|
||||||
|
tree.set(tcpSampler, samplerHashTree);
|
||||||
setUserParameters(samplerHashTree);
|
setUserParameters(samplerHashTree);
|
||||||
if (tcpPreProcessor != null && StringUtils.isNotBlank(tcpPreProcessor.getScript())) {
|
if (tcpPreProcessor != null && StringUtils.isNotBlank(tcpPreProcessor.getScript())) {
|
||||||
samplerHashTree.add(tcpPreProcessor.getShellProcessor());
|
samplerHashTree.add(tcpPreProcessor.getShellProcessor());
|
||||||
}
|
}
|
||||||
//增加误报、全局断言
|
//增加误报、全局断言
|
||||||
HashTreeUtil.addPositive(envConfig, samplerHashTree, config, this.getProjectId());
|
HashTreeUtil.addPositive(envConfig, samplerHashTree, config, this.getProjectId(), tcpSampler);
|
||||||
//处理全局前后置脚本(步骤内)
|
//处理全局前后置脚本(步骤内)
|
||||||
String environmentId = this.getEnvironmentId();
|
String environmentId = this.getEnvironmentId();
|
||||||
if (environmentId == null) {
|
if (environmentId == null) {
|
||||||
|
@ -154,15 +154,9 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
}
|
}
|
||||||
//根据配置将脚本放置在私有脚本之前
|
//根据配置将脚本放置在私有脚本之前
|
||||||
JMeterScriptUtil.setScriptByEnvironmentConfig(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), environmentId, config, false);
|
JMeterScriptUtil.setScriptByEnvironmentConfig(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), environmentId, config, false);
|
||||||
HashTreeUtil hashTreeUtil = new HashTreeUtil();
|
|
||||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||||
hashTree = ElementUtil.order(hashTree);
|
hashTree = ElementUtil.order(hashTree);
|
||||||
EnvironmentConfig finalEnvConfig = envConfig;
|
|
||||||
hashTree.forEach(el -> {
|
hashTree.forEach(el -> {
|
||||||
if (el instanceof MsAssertions && finalEnvConfig != null) {
|
|
||||||
//断言设置需要和全局断言、误报进行去重
|
|
||||||
el = hashTreeUtil.duplicateRegexInAssertions(ElementUtil.copyAssertion(finalEnvConfig.getAssertions()), (MsAssertions) el);
|
|
||||||
}
|
|
||||||
el.toHashTree(samplerHashTree, el.getHashTree(), config);
|
el.toHashTree(samplerHashTree, el.getHashTree(), config);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.api.dto.scenario;
|
package io.metersphere.api.dto.scenario;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.definition.FakeError;
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
||||||
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
|
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
|
||||||
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
||||||
|
@ -30,6 +31,7 @@ public class HttpConfig {
|
||||||
private List<MsAssertions> assertions;
|
private List<MsAssertions> assertions;
|
||||||
private List<MsAssertions> errorReportAssertions;
|
private List<MsAssertions> errorReportAssertions;
|
||||||
private String description;
|
private String description;
|
||||||
|
private FakeError fakeError;
|
||||||
|
|
||||||
|
|
||||||
public HttpConfig initHttpConfig(HttpConfigCondition configCondition) {
|
public HttpConfig initHttpConfig(HttpConfigCondition configCondition) {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package io.metersphere.api.jmeter;
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
import io.metersphere.api.dto.MsgDTO;
|
import io.metersphere.api.dto.MsgDTO;
|
||||||
|
import io.metersphere.api.dto.RequestResultExpandDTO;
|
||||||
import io.metersphere.commons.constants.ApiRunMode;
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
import io.metersphere.commons.constants.KafkaTopicConstants;
|
import io.metersphere.commons.constants.KafkaTopicConstants;
|
||||||
import io.metersphere.commons.utils.*;
|
import io.metersphere.commons.utils.*;
|
||||||
|
import io.metersphere.dto.RequestResult;
|
||||||
import io.metersphere.service.ApiExecutionQueueService;
|
import io.metersphere.service.ApiExecutionQueueService;
|
||||||
import io.metersphere.service.RedisTemplateService;
|
import io.metersphere.service.RedisTemplateService;
|
||||||
import io.metersphere.service.TestResultService;
|
import io.metersphere.service.TestResultService;
|
||||||
|
@ -42,6 +44,9 @@ public class MsKafkaListener {
|
||||||
@Resource
|
@Resource
|
||||||
private RedisTemplateService redisTemplateService;
|
private RedisTemplateService redisTemplateService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ApiDefinitionEnvService apiDefinitionEnvService;
|
||||||
|
|
||||||
private final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
|
private final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
|
||||||
CORE_POOL_SIZE,
|
CORE_POOL_SIZE,
|
||||||
MAX_POOL_SIZE,
|
MAX_POOL_SIZE,
|
||||||
|
@ -76,9 +81,19 @@ public class MsKafkaListener {
|
||||||
LoggerUtil.info("接收到执行结果:", record.key());
|
LoggerUtil.info("接收到执行结果:", record.key());
|
||||||
if (ObjectUtils.isNotEmpty(record.value()) && WebSocketUtil.has(record.key().toString())) {
|
if (ObjectUtils.isNotEmpty(record.value()) && WebSocketUtil.has(record.key().toString())) {
|
||||||
MsgDTO dto = JSONUtil.parseObject(record.value(), MsgDTO.class);
|
MsgDTO dto = JSONUtil.parseObject(record.value(), MsgDTO.class);
|
||||||
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name()) && dto.getContent().startsWith("result_")) {
|
if (StringUtils.isNotBlank(dto.getContent()) && dto.getContent().startsWith("result_")) {
|
||||||
ApiDefinitionEnvService apiDefinitionEnvService = CommonBeanFactory.getBean(ApiDefinitionEnvService.class);
|
String content = dto.getContent().substring(7);
|
||||||
apiDefinitionEnvService.setEnvAndPoolName(dto);
|
if (StringUtils.isNotBlank(content)) {
|
||||||
|
RequestResult baseResult = JSONUtil.parseObject(content, RequestResult.class);
|
||||||
|
if (ObjectUtils.isNotEmpty(baseResult)) {
|
||||||
|
//解析是否含有误报库信息
|
||||||
|
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(baseResult);
|
||||||
|
dto.setContent(StringUtils.join("result_", JSON.toJSONString(expandDTO)));
|
||||||
|
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name()) && dto.getContent().startsWith("result_")) {
|
||||||
|
apiDefinitionEnvService.setEnvAndPoolName(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WebSocketUtil.sendMessageSingle(dto);
|
WebSocketUtil.sendMessageSingle(dto);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,256 +0,0 @@
|
||||||
package io.metersphere.commons.utils;
|
|
||||||
|
|
||||||
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
|
|
||||||
import io.metersphere.commons.enums.ApiReportStatus;
|
|
||||||
import io.metersphere.dto.ErrorReportAssertionResult;
|
|
||||||
import io.metersphere.dto.RequestResult;
|
|
||||||
import io.metersphere.dto.ResponseAssertionResult;
|
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
|
||||||
import org.apache.commons.collections.MapUtils;
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 误报解析类
|
|
||||||
*/
|
|
||||||
public class ErrorReportLibraryUtil {
|
|
||||||
|
|
||||||
private static final String ERROR_REPORT_NAME_START = "ErrorReportAssertion:";
|
|
||||||
private static final String ERROR_REPORT_SUCCESS_MESSAGE_FLAG = " Final result is success";
|
|
||||||
public static final String ASSERTION_CONTENT_REGEX_DELIMITER = "--REGEX-->";
|
|
||||||
|
|
||||||
public static ErrorReportLibraryParseDTO parseAssertions(RequestResult result) {
|
|
||||||
ErrorReportLibraryParseDTO returnDTO = new ErrorReportLibraryParseDTO();
|
|
||||||
if (result != null && result.getResponseResult() != null && CollectionUtils.isNotEmpty(result.getResponseResult().getAssertions())) {
|
|
||||||
AssertionParserResult assertionParserResult = parserAndFormatAssertion(result.getResponseResult().getAssertions());
|
|
||||||
List<ResponseAssertionResult> errorReportAssertionList = assertionParserResult.errorReportAssertionList;
|
|
||||||
Map<String, List<ResponseAssertionResult>> successAssertionMessageMap = assertionParserResult.successAssertionMessageMap;
|
|
||||||
Map<String, List<ResponseAssertionResult>> errorAssertionMessageMap = assertionParserResult.errorAssertionMessageMap;
|
|
||||||
boolean higherThanSuccess = assertionParserResult.higherThanSuccess;
|
|
||||||
boolean higherThanError = assertionParserResult.higherThanError;
|
|
||||||
/*
|
|
||||||
默认优先级(higherThanSuccess=false,higherThanError=false):
|
|
||||||
1.如果一个请求同时有 成功、误报、失败 三个断言(断言规则不一样)时,那么请求最终结果处理成失败,展示匹配到的误报断言;
|
|
||||||
2.如果一个请求同时有 失败、误报(断言规则不一样)那么处理成失败,展示匹配到的误报断言;
|
|
||||||
3.如果一个请求同时有 成功、误报(断言规则不一样)那么处理成误报,展示匹配到的误报断言;
|
|
||||||
4.如果一个请求同时有 成功、误报(断言规则一样)那么处理成成功,不展示匹配到的误报断言。
|
|
||||||
能和误报断言匹配上的成功断言,都转为成功断言;
|
|
||||||
如果含有失败断言,则结果处理成失败,展示剩下的误报断言
|
|
||||||
如果还有误报断言,那么结果处理成误报,展示剩下的误报断言
|
|
||||||
最后就是成功
|
|
||||||
|
|
||||||
如果配置的误报与失败的优先级 / 误报与成功的优先级 与上述出现偏差,则对应的结果也会改变
|
|
||||||
*/
|
|
||||||
if (CollectionUtils.isNotEmpty(errorReportAssertionList)) {
|
|
||||||
List<ResponseAssertionResult> unMatchErrorReportAssertions = new ArrayList<>();
|
|
||||||
Map<String, List<ResponseAssertionResult>> passedErrorReportAssertionMap = new HashMap<>();
|
|
||||||
|
|
||||||
//过滤出没有命中的误报断言,并整理出命中误报断言的数据
|
|
||||||
for (ResponseAssertionResult assertion : errorReportAssertionList) {
|
|
||||||
if (StringUtils.endsWith(assertion.getMessage(), ERROR_REPORT_SUCCESS_MESSAGE_FLAG)) {
|
|
||||||
String regexString = assertion.getContent();
|
|
||||||
if (passedErrorReportAssertionMap.containsKey(regexString))
|
|
||||||
passedErrorReportAssertionMap.get(regexString).add(assertion);
|
|
||||||
else {
|
|
||||||
List<ResponseAssertionResult> list = new ArrayList<>();
|
|
||||||
list.add(assertion);
|
|
||||||
passedErrorReportAssertionMap.put(regexString, list);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unMatchErrorReportAssertions.add(assertion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//根据配置来筛选断言、获取误报编码、获取接口状态是否是误报
|
|
||||||
AssertionFilterResult filterResult = filterAssertions(passedErrorReportAssertionMap, successAssertionMessageMap, errorAssertionMessageMap, result.isSuccess(), higherThanSuccess, higherThanError);
|
|
||||||
int filteredSuccessAssertionCount = unMatchErrorReportAssertions.size() + filterResult.filteredSuccessAssertionList.size();
|
|
||||||
unMatchErrorReportAssertions.addAll(filterResult.filteredSuccessAssertionList);
|
|
||||||
unMatchErrorReportAssertions.addAll(filterResult.filteredErrorAssertionList);
|
|
||||||
returnDTO.setRequestStatus(filterResult.requestStatus);
|
|
||||||
returnDTO.setErrorCodeList(filterResult.errorCodeList);
|
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(unMatchErrorReportAssertions)) {
|
|
||||||
// 未被误报断言匹配到的结果,清除该请求的误报断言记录,并将断言涉及到的统计结果恢复正常
|
|
||||||
result.setTotalAssertions(result.getTotalAssertions() - unMatchErrorReportAssertions.size());
|
|
||||||
int passAssertionCount = (result.getPassAssertions() - filteredSuccessAssertionCount);
|
|
||||||
if (passAssertionCount < 0) {
|
|
||||||
result.setPassAssertions(0);
|
|
||||||
} else {
|
|
||||||
result.setPassAssertions(passAssertionCount);
|
|
||||||
}
|
|
||||||
List<ResponseAssertionResult> allAssertions = result.getResponseResult().getAssertions();
|
|
||||||
List<ResponseAssertionResult> newAssertions = new ArrayList<>();
|
|
||||||
|
|
||||||
allAssertionForeach:
|
|
||||||
for (ResponseAssertionResult assertion : allAssertions) {
|
|
||||||
for (ResponseAssertionResult unMatchAssertion : unMatchErrorReportAssertions) {
|
|
||||||
if (StringUtils.equals(unMatchAssertion.getContent(), assertion.getContent())) {
|
|
||||||
continue allAssertionForeach;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newAssertions.add(assertion);
|
|
||||||
}
|
|
||||||
result.getResponseResult().getAssertions().clear();
|
|
||||||
result.getResponseResult().getAssertions().addAll(newAssertions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
returnDTO.setResult(result);
|
|
||||||
return returnDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 过滤断言并统计最后结果
|
|
||||||
* 1.higherThanError=true:含有误报断言就为误报,否则就为失败
|
|
||||||
* 2.higherThanSuccess=true:含有误报断言就为误报,否则就为成功
|
|
||||||
*
|
|
||||||
* @param errorReportAssertionMap 匹配到的误报断言
|
|
||||||
* @param successAssertionMap 匹配到的成功断言
|
|
||||||
* @param errorAssertionMap 匹配到的失败断言
|
|
||||||
* @param higherThanSuccess 误报断言优先级小于成功断言优先级
|
|
||||||
* @param higherThanError 误报断言优先级大于成功断言优先级
|
|
||||||
*/
|
|
||||||
private static AssertionFilterResult filterAssertions(Map<String, List<ResponseAssertionResult>> errorReportAssertionMap,
|
|
||||||
Map<String, List<ResponseAssertionResult>> successAssertionMap,
|
|
||||||
Map<String, List<ResponseAssertionResult>> errorAssertionMap,
|
|
||||||
boolean resultIsSuccess, boolean higherThanSuccess, boolean higherThanError) {
|
|
||||||
AssertionFilterResult result = new AssertionFilterResult();
|
|
||||||
if (MapUtils.isNotEmpty(errorReportAssertionMap)) {
|
|
||||||
List<ResponseAssertionResult> removedSuccessList = removeAssertions(errorReportAssertionMap, successAssertionMap, higherThanSuccess);
|
|
||||||
if (CollectionUtils.isNotEmpty(removedSuccessList)) {
|
|
||||||
result.filteredSuccessAssertionList.addAll(removedSuccessList);
|
|
||||||
}
|
|
||||||
List<ResponseAssertionResult> removedErrorList = removeAssertions(errorReportAssertionMap, errorAssertionMap, higherThanError);
|
|
||||||
if (CollectionUtils.isNotEmpty(removedErrorList)) {
|
|
||||||
if (higherThanError) {
|
|
||||||
result.filteredErrorAssertionList.addAll(removedErrorList);
|
|
||||||
} else {
|
|
||||||
result.filteredSuccessAssertionList.addAll(removedErrorList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
for (List<ResponseAssertionResult> list : errorReportAssertionMap.values()) {
|
|
||||||
list.forEach(item -> {
|
|
||||||
String assertionName = item.getName();
|
|
||||||
if (StringUtils.startsWith(assertionName, ERROR_REPORT_NAME_START)) {
|
|
||||||
String errorCode = StringUtils.substring(assertionName, ERROR_REPORT_NAME_START.length());
|
|
||||||
result.errorCodeList.add(errorCode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(result.errorCodeList)) {
|
|
||||||
if ((higherThanError && !resultIsSuccess) || (higherThanSuccess && resultIsSuccess)) {
|
|
||||||
result.requestStatus = ApiReportStatus.FAKE_ERROR.name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogUtil.info(" FAKE_ERROR result: config-higherThanError:" + higherThanError
|
|
||||||
+ ", config-higherThanSuccess:" + higherThanSuccess
|
|
||||||
+ ", resultIsSuccess: " + resultIsSuccess
|
|
||||||
+ ", isFakeError: " + ((higherThanError && !resultIsSuccess) || (higherThanSuccess && resultIsSuccess))
|
|
||||||
+ "; status:" + result.requestStatus);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将匹配的断言移除
|
|
||||||
*
|
|
||||||
* @param firstMap
|
|
||||||
* @param secondMap
|
|
||||||
* @param removeDataInSecondMap 是否移除map2中的数据?true:移除map2中的数据 false:移除map1中的数据
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static List<ResponseAssertionResult> removeAssertions(Map<String, List<ResponseAssertionResult>> firstMap, Map<String, List<ResponseAssertionResult>> secondMap, boolean removeDataInSecondMap) {
|
|
||||||
List<ResponseAssertionResult> returnList = new ArrayList<>();
|
|
||||||
if (MapUtils.isNotEmpty(firstMap) && MapUtils.isNotEmpty(secondMap)) {
|
|
||||||
if (removeDataInSecondMap) {
|
|
||||||
for (String regex : firstMap.keySet()) {
|
|
||||||
if (secondMap.containsKey(regex)) {
|
|
||||||
returnList.addAll(secondMap.get(regex));
|
|
||||||
secondMap.remove(regex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (String regex : secondMap.keySet()) {
|
|
||||||
if (firstMap.containsKey(regex)) {
|
|
||||||
returnList.addAll(firstMap.get(regex));
|
|
||||||
firstMap.remove(regex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析并重新格式化请求中的所有断言
|
|
||||||
*
|
|
||||||
* @param assertions
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static AssertionParserResult parserAndFormatAssertion(List<ResponseAssertionResult> assertions) {
|
|
||||||
AssertionParserResult result = new AssertionParserResult();
|
|
||||||
for (ResponseAssertionResult assertion : assertions) {
|
|
||||||
if (assertion instanceof ErrorReportAssertionResult || StringUtils.startsWith(assertion.getName(), ERROR_REPORT_NAME_START)) {
|
|
||||||
String expression = assertion.getContent().trim();
|
|
||||||
if (StringUtils.contains(expression, ASSERTION_CONTENT_REGEX_DELIMITER)) {
|
|
||||||
String[] contentArr = expression.split(ASSERTION_CONTENT_REGEX_DELIMITER);
|
|
||||||
assertion.setContent(contentArr[0]);
|
|
||||||
if (contentArr.length == 3) {
|
|
||||||
result.higherThanSuccess = BooleanUtils.toBoolean(contentArr[1]);
|
|
||||||
result.higherThanError = BooleanUtils.toBoolean(contentArr[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.errorReportAssertionList.add(assertion);
|
|
||||||
} else {
|
|
||||||
if (StringUtils.isNotEmpty(assertion.getContent())) {
|
|
||||||
String expression = assertion.getContent().trim();
|
|
||||||
String regexString = expression;
|
|
||||||
if (regexString.contains(ASSERTION_CONTENT_REGEX_DELIMITER)) {
|
|
||||||
regexString = expression.split(ASSERTION_CONTENT_REGEX_DELIMITER)[1];
|
|
||||||
assertion.setContent(expression.split(ASSERTION_CONTENT_REGEX_DELIMITER)[0]);
|
|
||||||
}
|
|
||||||
if (assertion.isPass()) {
|
|
||||||
if (result.successAssertionMessageMap.containsKey(regexString))
|
|
||||||
result.successAssertionMessageMap.get(regexString).add(assertion);
|
|
||||||
else {
|
|
||||||
List<ResponseAssertionResult> list = new ArrayList<>();
|
|
||||||
list.add(assertion);
|
|
||||||
result.successAssertionMessageMap.put(regexString, list);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (result.errorAssertionMessageMap.containsKey(regexString))
|
|
||||||
result.errorAssertionMessageMap.get(regexString).add(assertion);
|
|
||||||
else {
|
|
||||||
List<ResponseAssertionResult> list = new ArrayList<>();
|
|
||||||
list.add(assertion);
|
|
||||||
result.errorAssertionMessageMap.put(regexString, list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AssertionParserResult {
|
|
||||||
boolean higherThanSuccess = false;
|
|
||||||
boolean higherThanError = false;
|
|
||||||
List<ResponseAssertionResult> errorReportAssertionList = new ArrayList<>();
|
|
||||||
Map<String, List<ResponseAssertionResult>> successAssertionMessageMap = new HashMap<>();
|
|
||||||
Map<String, List<ResponseAssertionResult>> errorAssertionMessageMap = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
class AssertionFilterResult {
|
|
||||||
String requestStatus;
|
|
||||||
List<String> errorCodeList = new ArrayList<>();
|
|
||||||
List<ResponseAssertionResult> filteredSuccessAssertionList = new ArrayList<>();
|
|
||||||
List<ResponseAssertionResult> filteredErrorAssertionList = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package io.metersphere.commons.utils;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.FakeErrorLibraryDTO;
|
||||||
|
import io.metersphere.api.dto.definition.FakeError;
|
||||||
|
import io.metersphere.api.dto.definition.MsRegexDTO;
|
||||||
|
import io.metersphere.base.domain.ErrorReportLibraryExample;
|
||||||
|
import io.metersphere.base.domain.ErrorReportLibraryWithBLOBs;
|
||||||
|
import io.metersphere.commons.enums.ApiReportStatus;
|
||||||
|
import io.metersphere.dto.RequestResult;
|
||||||
|
import io.metersphere.utils.JsonUtils;
|
||||||
|
import io.metersphere.xpack.fake.error.ErrorReportLibraryService;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 误报解析类
|
||||||
|
*
|
||||||
|
* @author xiaogang
|
||||||
|
*/
|
||||||
|
public class FakeErrorParse {
|
||||||
|
|
||||||
|
public static FakeErrorLibraryDTO parseAssertions(RequestResult result) {
|
||||||
|
FakeErrorLibraryDTO fakeError = new FakeErrorLibraryDTO();
|
||||||
|
if (StringUtils.isNotBlank(result.getFakeErrorMessage())) {
|
||||||
|
FakeError errorReportDTO = JsonUtils.parseObject(result.getFakeErrorMessage(), FakeError.class);
|
||||||
|
ErrorReportLibraryService service = CommonBeanFactory.getBean(ErrorReportLibraryService.class);
|
||||||
|
ErrorReportLibraryExample example = new ErrorReportLibraryExample();
|
||||||
|
example.createCriteria().andProjectIdEqualTo(errorReportDTO.getProjectId()).andStatusEqualTo(true);
|
||||||
|
List<ErrorReportLibraryWithBLOBs> bloBs = service.selectByExampleWithBLOBs(example);
|
||||||
|
List<MsRegexDTO> regexList = new ArrayList<>();
|
||||||
|
bloBs.forEach(item -> {
|
||||||
|
if (StringUtils.isNotEmpty(item.getContent())) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> assertionMap = JSON.parseObject(item.getContent(), Map.class);
|
||||||
|
if (assertionMap != null) {
|
||||||
|
MsRegexDTO regexConfig = JSON.parseObject(JSONUtil.toJSONString(assertionMap.get("regexConfig")), MsRegexDTO.class);
|
||||||
|
regexConfig.setErrorCode(item.getErrorCode());
|
||||||
|
regexList.add(regexConfig);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//根据配置来筛选断言、获取误报编码、获取接口状态是否是误报
|
||||||
|
List<String> errorCodeList = new ArrayList<>();
|
||||||
|
regexList.forEach(item -> {
|
||||||
|
if (StringUtils.isNotEmpty(item.getSubject())) {
|
||||||
|
switch (item.getSubject()) {
|
||||||
|
case "Response Code" ->
|
||||||
|
item.setPass(parseResponseCode(result.getResponseResult().getResponseCode(), item.getValue(), item.getCondition()));
|
||||||
|
|
||||||
|
case "Response Headers" ->
|
||||||
|
item.setPass(parseResponseCode(result.getResponseResult().getHeaders(), item.getValue(), item.getCondition()));
|
||||||
|
|
||||||
|
case "Response Data" ->
|
||||||
|
item.setPass(parseResponseCode(result.getResponseResult().getBody(), item.getValue(), item.getCondition()));
|
||||||
|
default -> item.setPass(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.isPass()) {
|
||||||
|
errorCodeList.add(item.getErrorCode());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
boolean higherThanError = errorReportDTO.isHigherThanError();
|
||||||
|
boolean higherThanSuccess = errorReportDTO.isHigherThanSuccess();
|
||||||
|
if (CollectionUtils.isNotEmpty(errorCodeList)) {
|
||||||
|
if ((higherThanError && !result.isSuccess()) || (higherThanSuccess && result.isSuccess())) {
|
||||||
|
fakeError.setRequestStatus(ApiReportStatus.FAKE_ERROR.name());
|
||||||
|
}
|
||||||
|
fakeError.setErrorCodeList(errorCodeList);
|
||||||
|
}
|
||||||
|
LogUtil.info(" FAKE_ERROR result: config-higherThanError:" + higherThanError
|
||||||
|
+ ", config-higherThanSuccess:" + higherThanSuccess
|
||||||
|
+ ", resultIsSuccess: " + result.isSuccess()
|
||||||
|
+ ", isFakeError: " + ((higherThanError && !result.isSuccess()) || (higherThanSuccess && result.isSuccess()))
|
||||||
|
+ "; status:" + fakeError.getRequestStatus());
|
||||||
|
}
|
||||||
|
fakeError.setResult(result);
|
||||||
|
return fakeError;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean parseResponseCode(String result, String regexDTO, String condition) {
|
||||||
|
return switch (condition.toUpperCase()) {
|
||||||
|
case "CONTAINS" -> result.contains(regexDTO);
|
||||||
|
|
||||||
|
case "NOT_CONTAINS" -> notContains(result, regexDTO);
|
||||||
|
|
||||||
|
case "EQUALS" -> StringUtils.equals(result, regexDTO);
|
||||||
|
|
||||||
|
case "START_WITH" -> result.startsWith(regexDTO);
|
||||||
|
|
||||||
|
case "END_WITH" -> result.endsWith(regexDTO);
|
||||||
|
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean notContains(String result, String regexDTO) {
|
||||||
|
return !result.contains(regexDTO);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
package io.metersphere.commons.utils;
|
package io.metersphere.commons.utils;
|
||||||
|
|
||||||
import io.metersphere.api.dto.RunningParamKeys;
|
import io.metersphere.api.dto.RunningParamKeys;
|
||||||
|
import io.metersphere.api.dto.definition.FakeError;
|
||||||
import io.metersphere.api.dto.definition.request.ElementUtil;
|
import io.metersphere.api.dto.definition.request.ElementUtil;
|
||||||
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertionRegex;
|
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
||||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
||||||
|
@ -15,7 +15,6 @@ import io.metersphere.dto.JmeterRunRequestDTO;
|
||||||
import io.metersphere.environment.service.BaseEnvironmentService;
|
import io.metersphere.environment.service.BaseEnvironmentService;
|
||||||
import io.metersphere.metadata.service.FileMetadataService;
|
import io.metersphere.metadata.service.FileMetadataService;
|
||||||
import io.metersphere.request.BodyFile;
|
import io.metersphere.request.BodyFile;
|
||||||
import io.metersphere.service.ExtErrorReportLibraryService;
|
|
||||||
import io.metersphere.utils.LoggerUtil;
|
import io.metersphere.utils.LoggerUtil;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
@ -23,6 +22,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.extractor.JSR223PostProcessor;
|
import org.apache.jmeter.extractor.JSR223PostProcessor;
|
||||||
import org.apache.jmeter.modifiers.JSR223PreProcessor;
|
import org.apache.jmeter.modifiers.JSR223PreProcessor;
|
||||||
import org.apache.jmeter.protocol.java.sampler.JSR223Sampler;
|
import org.apache.jmeter.protocol.java.sampler.JSR223Sampler;
|
||||||
|
import org.apache.jmeter.protocol.jdbc.sampler.JDBCSampler;
|
||||||
|
import org.apache.jmeter.protocol.tcp.sampler.TCPSampler;
|
||||||
|
import org.apache.jmeter.samplers.SampleResult;
|
||||||
|
import org.apache.jmeter.testelement.AbstractTestElement;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
@ -182,53 +185,19 @@ public class HashTreeUtil {
|
||||||
return execute_env_param_dataMap;
|
return execute_env_param_dataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MsAssertions duplicateRegexInAssertions(List<MsAssertions> compareList, MsAssertions target) {
|
public static void addPositive(EnvironmentConfig envConfig, HashTree samplerHashTree, ParameterConfig config, String projectId, AbstractTestElement sample) {
|
||||||
if (target != null && CollectionUtils.isNotEmpty(target.getRegex())) {
|
|
||||||
List<MsAssertionRegex> compareRegexList = new ArrayList<>();
|
|
||||||
if (CollectionUtils.isNotEmpty(compareList)) {
|
|
||||||
for (MsAssertions assertions : compareList) {
|
|
||||||
if (assertions != null && CollectionUtils.isNotEmpty(assertions.getRegex())) {
|
|
||||||
compareRegexList.addAll(assertions.getRegex());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MsAssertionRegex> duplicatedList = new ArrayList<>();
|
|
||||||
for (MsAssertionRegex regex : target.getRegex()) {
|
|
||||||
boolean isExit = false;
|
|
||||||
for (MsAssertionRegex compareRegex : compareRegexList) {
|
|
||||||
if (StringUtils.equals(regex.getType(), compareRegex.getType())
|
|
||||||
&& StringUtils.equals(regex.getSubject(), compareRegex.getSubject())
|
|
||||||
&& StringUtils.equals(regex.getExpression(), compareRegex.getExpression())) {
|
|
||||||
isExit = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isExit) {
|
|
||||||
duplicatedList.add(regex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target.setRegex(duplicatedList);
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<MsAssertions> getErrorReportByProjectId(String projectId, boolean higherThanSuccess, boolean higherThanError) {
|
|
||||||
ExtErrorReportLibraryService service = CommonBeanFactory.getBean(ExtErrorReportLibraryService.class);
|
|
||||||
if (service == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
return service.getAssertionByProjectIdAndStatusIsOpen(projectId, higherThanSuccess, higherThanError);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addPositive(EnvironmentConfig envConfig, HashTree samplerHashTree, ParameterConfig config, String projectId) {
|
|
||||||
if (envConfig == null) {
|
if (envConfig == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!config.isOperating() && envConfig.isUseErrorCode()) {
|
if (!config.isOperating() && envConfig.isUseErrorCode()) {
|
||||||
List<MsAssertions> errorReportAssertion = HashTreeUtil.getErrorReportByProjectId(projectId, envConfig.isHigherThanSuccess(), envConfig.isHigherThanError());
|
FakeError fakeError = new FakeError();
|
||||||
for (MsAssertions assertion : errorReportAssertion) {
|
fakeError.setHigherThanError(envConfig.isHigherThanError());
|
||||||
assertion.toHashTree(samplerHashTree, assertion.getHashTree(), config);
|
fakeError.setProjectId(projectId);
|
||||||
|
fakeError.setHigherThanSuccess(envConfig.isHigherThanSuccess());
|
||||||
|
if (sample instanceof JDBCSampler) {
|
||||||
|
sample.setProperty(SampleResult.MS_FAKE_ERROR, JSONUtil.toJSONString(fakeError));
|
||||||
|
} else if (sample instanceof TCPSampler) {
|
||||||
|
sample.setProperty(SampleResult.MS_FAKE_ERROR, JSONUtil.toJSONString(fakeError));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(envConfig.getAssertions())) {
|
if (CollectionUtils.isNotEmpty(envConfig.getAssertions())) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package io.metersphere.commons.utils;
|
||||||
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
||||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
|
import io.metersphere.api.dto.FakeErrorLibraryDTO;
|
||||||
import io.metersphere.api.dto.RequestResultExpandDTO;
|
import io.metersphere.api.dto.RequestResultExpandDTO;
|
||||||
import io.metersphere.commons.enums.ApiReportStatus;
|
import io.metersphere.commons.enums.ApiReportStatus;
|
||||||
import io.metersphere.commons.enums.ResponseFormatType;
|
import io.metersphere.commons.enums.ResponseFormatType;
|
||||||
|
@ -24,7 +24,7 @@ public class ResponseUtil {
|
||||||
//根据responseheader的信息来处理返回数据
|
//根据responseheader的信息来处理返回数据
|
||||||
baseResult = ResponseUtil.parseResponseBodyByHeader(baseResult);
|
baseResult = ResponseUtil.parseResponseBodyByHeader(baseResult);
|
||||||
//解析是否含有误报库信息
|
//解析是否含有误报库信息
|
||||||
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(baseResult);
|
FakeErrorLibraryDTO errorCodeDTO = FakeErrorParse.parseAssertions(baseResult);
|
||||||
RequestResult requestResult = errorCodeDTO.getResult();
|
RequestResult requestResult = errorCodeDTO.getResult();
|
||||||
RequestResultExpandDTO expandDTO = new RequestResultExpandDTO();
|
RequestResultExpandDTO expandDTO = new RequestResultExpandDTO();
|
||||||
BeanUtils.copyBean(expandDTO, requestResult);
|
BeanUtils.copyBean(expandDTO, requestResult);
|
||||||
|
|
|
@ -2,8 +2,7 @@ package io.metersphere.commons.utils;
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.api.dto.ApiScenarioReportBaseInfoDTO;
|
import io.metersphere.api.dto.ApiScenarioReportBaseInfoDTO;
|
||||||
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
|
import io.metersphere.api.dto.FakeErrorLibraryDTO;
|
||||||
import io.metersphere.base.domain.ApiScenarioReportResult;
|
|
||||||
import io.metersphere.base.domain.ApiScenarioReportResultWithBLOBs;
|
import io.metersphere.base.domain.ApiScenarioReportResultWithBLOBs;
|
||||||
import io.metersphere.commons.enums.ApiReportStatus;
|
import io.metersphere.commons.enums.ApiReportStatus;
|
||||||
import io.metersphere.dto.RequestResult;
|
import io.metersphere.dto.RequestResult;
|
||||||
|
@ -12,27 +11,13 @@ import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ResultConversionUtil {
|
public class ResultConversionUtil {
|
||||||
|
|
||||||
public static List<ApiScenarioReportResult> getApiScenarioReportResults(String reportId, List<RequestResult> requestResults) {
|
|
||||||
//解析误报内容
|
|
||||||
List<ApiScenarioReportResult> list = new LinkedList<>();
|
|
||||||
if (CollectionUtils.isEmpty(requestResults)) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
requestResults.forEach(item -> {
|
|
||||||
list.add(getApiScenarioReportResult(reportId, item));
|
|
||||||
});
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiScenarioReportResultWithBLOBs getApiScenarioReportResult(String reportId, RequestResult requestResult) {
|
public static ApiScenarioReportResultWithBLOBs getApiScenarioReportResult(String reportId, RequestResult requestResult) {
|
||||||
//解析误报内容
|
//解析误报内容
|
||||||
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(requestResult);
|
FakeErrorLibraryDTO errorCodeDTO = FakeErrorParse.parseAssertions(requestResult);
|
||||||
RequestResult result = errorCodeDTO.getResult();
|
RequestResult result = errorCodeDTO.getResult();
|
||||||
String resourceId = result.getResourceId();
|
String resourceId = result.getResourceId();
|
||||||
|
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
package io.metersphere.service;
|
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertionDuration;
|
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertionRegex;
|
|
||||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
|
||||||
import io.metersphere.api.dto.definition.request.assertions.document.MsAssertionDocument;
|
|
||||||
import io.metersphere.base.domain.ErrorReportLibraryExample;
|
|
||||||
import io.metersphere.base.domain.ErrorReportLibraryWithBLOBs;
|
|
||||||
import io.metersphere.commons.utils.*;
|
|
||||||
import io.metersphere.xpack.fake.error.ErrorReportLibraryService;
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author song.tianyang
|
|
||||||
* @Date 2022/1/3 3:51 下午
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public class ExtErrorReportLibraryService {
|
|
||||||
public List<MsAssertions> getAssertionByProjectIdAndStatusIsOpen(String projectId, boolean higherThanSuccess, boolean higherThanError) {
|
|
||||||
ErrorReportLibraryService service = CommonBeanFactory.getBean(ErrorReportLibraryService.class);
|
|
||||||
if (service == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
List<MsAssertions> returnList = new ArrayList<>();
|
|
||||||
ErrorReportLibraryExample example = new ErrorReportLibraryExample();
|
|
||||||
example.createCriteria().andProjectIdEqualTo(projectId).andStatusEqualTo(true);
|
|
||||||
List<ErrorReportLibraryWithBLOBs> bloBs = service.selectByExampleWithBLOBs(example);
|
|
||||||
bloBs.forEach(item -> {
|
|
||||||
if (StringUtils.isNotEmpty(item.getContent())) {
|
|
||||||
try {
|
|
||||||
MsAssertions assertions = new MsAssertions();
|
|
||||||
Map<String, Object> assertionMap = JSON.parseObject(item.getContent(), Map.class);
|
|
||||||
if (assertionMap != null) {
|
|
||||||
MsAssertionDuration duration = JSONUtil.parseObject(JSONUtil.toJSONString(assertionMap.get("duration")), MsAssertionDuration.class);
|
|
||||||
List<MsAssertionRegex> regexList = JSON.parseArray(JSONUtil.toJSONString(assertionMap.get("regex")), MsAssertionRegex.class);
|
|
||||||
MsAssertionDocument document = JSONUtil.parseObject(JSONUtil.toJSONString(assertionMap.get("document")), MsAssertionDocument.class);
|
|
||||||
assertions.setDuration(duration);
|
|
||||||
assertions.setRegex(regexList);
|
|
||||||
assertions.setDocument(document);
|
|
||||||
}
|
|
||||||
if (assertions != null && CollectionUtils.isNotEmpty(assertions.getRegex())) {
|
|
||||||
if (StringUtils.isEmpty(assertions.getRegex().get(0).getDescription())) {
|
|
||||||
String desc = assertions.getRegex().get(0).getSubject() + ":" + assertions.getRegex().get(0).getExpression()
|
|
||||||
+ ErrorReportLibraryUtil.ASSERTION_CONTENT_REGEX_DELIMITER + higherThanSuccess
|
|
||||||
+ ErrorReportLibraryUtil.ASSERTION_CONTENT_REGEX_DELIMITER + higherThanError;
|
|
||||||
assertions.getRegex().get(0).setDescription(desc);
|
|
||||||
}
|
|
||||||
assertions.setName("ErrorReportAssertion:" + item.getErrorCode());
|
|
||||||
returnList.add(assertions);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtil.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return returnList;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package io.metersphere.dto;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ErrorReportAssertionResult extends ResponseAssertionResult{
|
|
||||||
private String errorReportMessage;
|
|
||||||
|
|
||||||
public ErrorReportAssertionResult(String errorReportMessage){
|
|
||||||
this.errorReportMessage = errorReportMessage;
|
|
||||||
this.setMessage(errorReportMessage);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -53,4 +53,6 @@ public class RequestResult {
|
||||||
this.passAssertions++;
|
this.passAssertions++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String fakeErrorMessage;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ public class JMeterBase {
|
||||||
requestResult.setSuccess(result.isSuccessful());
|
requestResult.setSuccess(result.isSuccessful());
|
||||||
requestResult.setError(result.getErrorCount());
|
requestResult.setError(result.getErrorCount());
|
||||||
requestResult.setScenario(result.getScenario());
|
requestResult.setScenario(result.getScenario());
|
||||||
|
requestResult.setFakeErrorMessage(result.getFakeError());
|
||||||
if (result instanceof HTTPSampleResult) {
|
if (result instanceof HTTPSampleResult) {
|
||||||
HTTPSampleResult res = (HTTPSampleResult) result;
|
HTTPSampleResult res = (HTTPSampleResult) result;
|
||||||
requestResult.setCookies(res.getCookies());
|
requestResult.setCookies(res.getCookies());
|
||||||
|
@ -143,13 +144,7 @@ public class JMeterBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ResponseAssertionResult getResponseAssertionResult(AssertionResult assertionResult) {
|
private static ResponseAssertionResult getResponseAssertionResult(AssertionResult assertionResult) {
|
||||||
ResponseAssertionResult responseAssertionResult = null;
|
ResponseAssertionResult responseAssertionResult = new ResponseAssertionResult();
|
||||||
|
|
||||||
if (StringUtils.startsWith(assertionResult.getName(), "ErrorReportAssertion")) {
|
|
||||||
responseAssertionResult = new ErrorReportAssertionResult(assertionResult.getFailureMessage());
|
|
||||||
} else {
|
|
||||||
responseAssertionResult = new ResponseAssertionResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
responseAssertionResult.setName(assertionResult.getName());
|
responseAssertionResult.setName(assertionResult.getName());
|
||||||
if (StringUtils.isNotEmpty(assertionResult.getName()) && assertionResult.getName().indexOf("split==") != -1) {
|
if (StringUtils.isNotEmpty(assertionResult.getName()) && assertionResult.getName().indexOf("split==") != -1) {
|
||||||
|
|
|
@ -44,7 +44,6 @@ import java.util.concurrent.TimeUnit;
|
||||||
/**
|
/**
|
||||||
* This is a nice packaging for the various information returned from taking a
|
* This is a nice packaging for the various information returned from taking a
|
||||||
* sample of an entry.
|
* sample of an entry.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class SampleResult implements Serializable, Cloneable, Searchable {
|
public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
|
@ -143,6 +142,8 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
private static final String NULL_FILENAME = "NULL";
|
private static final String NULL_FILENAME = "NULL";
|
||||||
|
|
||||||
|
public static final String MS_FAKE_ERROR = "MS-FAKE-ERROR";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
if (START_TIMESTAMP) {
|
if (START_TIMESTAMP) {
|
||||||
log.info("Note: Sample TimeStamps are START times");
|
log.info("Note: Sample TimeStamps are START times");
|
||||||
|
@ -208,10 +209,14 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
private String label = "";// Never return null
|
private String label = "";// Never return null
|
||||||
|
|
||||||
/** Filename used by ResultSaver */
|
/**
|
||||||
|
* Filename used by ResultSaver
|
||||||
|
*/
|
||||||
private String resultFileName = "";
|
private String resultFileName = "";
|
||||||
|
|
||||||
/** The data used by the sampler */
|
/**
|
||||||
|
* The data used by the sampler
|
||||||
|
*/
|
||||||
private String samplerData;
|
private String samplerData;
|
||||||
|
|
||||||
private String threadName = ""; // Never return null
|
private String threadName = ""; // Never return null
|
||||||
|
@ -234,13 +239,21 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
private long idleTime = 0;// Allow for non-sample time
|
private long idleTime = 0;// Allow for non-sample time
|
||||||
|
|
||||||
/** Start of pause (if any) */
|
/**
|
||||||
|
* Start of pause (if any)
|
||||||
|
*/
|
||||||
private long pauseTime = 0;
|
private long pauseTime = 0;
|
||||||
|
|
||||||
private List<AssertionResult> assertionResults;
|
private List<AssertionResult> assertionResults;
|
||||||
|
|
||||||
private List<SampleResult> subResults;
|
private List<SampleResult> subResults;
|
||||||
|
|
||||||
|
private String fakeError;
|
||||||
|
|
||||||
|
public String getFakeError() {
|
||||||
|
return this.fakeError;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data type of the sample
|
* The data type of the sample
|
||||||
*
|
*
|
||||||
|
@ -266,25 +279,39 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
private String contentType = ""; // e.g. text/html; charset=utf-8
|
private String contentType = ""; // e.g. text/html; charset=utf-8
|
||||||
|
|
||||||
/** elapsed time */
|
/**
|
||||||
|
* elapsed time
|
||||||
|
*/
|
||||||
private long elapsedTime = 0;
|
private long elapsedTime = 0;
|
||||||
|
|
||||||
/** time to first response */
|
/**
|
||||||
|
* time to first response
|
||||||
|
*/
|
||||||
private long latency = 0;
|
private long latency = 0;
|
||||||
|
|
||||||
/** time to end connecting */
|
/**
|
||||||
|
* time to end connecting
|
||||||
|
*/
|
||||||
private long connectTime = 0;
|
private long connectTime = 0;
|
||||||
|
|
||||||
/** Way to signal what to do on Test */
|
/**
|
||||||
|
* Way to signal what to do on Test
|
||||||
|
*/
|
||||||
private TestLogicalAction testLogicalAction = TestLogicalAction.CONTINUE;
|
private TestLogicalAction testLogicalAction = TestLogicalAction.CONTINUE;
|
||||||
|
|
||||||
/** Should thread terminate? */
|
/**
|
||||||
|
* Should thread terminate?
|
||||||
|
*/
|
||||||
private boolean stopThread = false;
|
private boolean stopThread = false;
|
||||||
|
|
||||||
/** Should test terminate? */
|
/**
|
||||||
|
* Should test terminate?
|
||||||
|
*/
|
||||||
private boolean stopTest = false;
|
private boolean stopTest = false;
|
||||||
|
|
||||||
/** Should test terminate abruptly? */
|
/**
|
||||||
|
* Should test terminate abruptly?
|
||||||
|
*/
|
||||||
private boolean stopTestNow = false;
|
private boolean stopTestNow = false;
|
||||||
|
|
||||||
private int sampleCount = 1;
|
private int sampleCount = 1;
|
||||||
|
@ -295,10 +322,14 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
private long bodySize = 0;
|
private long bodySize = 0;
|
||||||
|
|
||||||
/** Currently active threads in this thread group */
|
/**
|
||||||
|
* Currently active threads in this thread group
|
||||||
|
*/
|
||||||
private volatile int groupThreads = 0;
|
private volatile int groupThreads = 0;
|
||||||
|
|
||||||
/** Currently active threads in all thread groups */
|
/**
|
||||||
|
* Currently active threads in all thread groups
|
||||||
|
*/
|
||||||
private volatile int allThreads = 0;
|
private volatile int allThreads = 0;
|
||||||
|
|
||||||
private final long nanoTimeOffset;
|
private final long nanoTimeOffset;
|
||||||
|
@ -342,6 +373,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
this.samplerId = sampler.getPropertyAsString("MS-ID");
|
this.samplerId = sampler.getPropertyAsString("MS-ID");
|
||||||
this.resourceId = sampler.getPropertyAsString("MS-RESOURCE-ID");
|
this.resourceId = sampler.getPropertyAsString("MS-RESOURCE-ID");
|
||||||
this.scenario = sampler.getPropertyAsString("MS-SCENARIO");
|
this.scenario = sampler.getPropertyAsString("MS-SCENARIO");
|
||||||
|
this.fakeError = sampler.getPropertyAsString(MS_FAKE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -399,13 +431,11 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Create a sample with a specific elapsed time but don't allow the times to
|
* Create a sample with a specific elapsed time but don't allow the times to
|
||||||
* be changed later
|
* be changed later
|
||||||
*
|
* <p>
|
||||||
* (only used by HTTPSampleResult)
|
* (only used by HTTPSampleResult)
|
||||||
*
|
*
|
||||||
* @param elapsed
|
* @param elapsed time
|
||||||
* time
|
* @param atend create the sample finishing now, else starting now
|
||||||
* @param atend
|
|
||||||
* create the sample finishing now, else starting now
|
|
||||||
*/
|
*/
|
||||||
protected SampleResult(long elapsed, boolean atend) {
|
protected SampleResult(long elapsed, boolean atend) {
|
||||||
this();
|
this();
|
||||||
|
@ -442,8 +472,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param propertiesToSave
|
* @param propertiesToSave The propertiesToSave to set.
|
||||||
* The propertiesToSave to set.
|
|
||||||
*/
|
*/
|
||||||
public void setSaveConfig(SampleSaveConfiguration propertiesToSave) {
|
public void setSaveConfig(SampleSaveConfiguration propertiesToSave) {
|
||||||
this.saveConfig = propertiesToSave;
|
this.saveConfig = propertiesToSave;
|
||||||
|
@ -460,13 +489,11 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Create a sample with specific start and end times for test purposes, but
|
* Create a sample with specific start and end times for test purposes, but
|
||||||
* don't allow the times to be changed later
|
* don't allow the times to be changed later
|
||||||
*
|
* <p>
|
||||||
* (used by StatVisualizerModel.Test)
|
* (used by StatVisualizerModel.Test)
|
||||||
*
|
*
|
||||||
* @param start
|
* @param start start time in milliseconds since unix epoch
|
||||||
* start time in milliseconds since unix epoch
|
* @param end end time in milliseconds since unix epoch
|
||||||
* @param end
|
|
||||||
* end time in milliseconds since unix epoch
|
|
||||||
* @return sample with given start and end time
|
* @return sample with given start and end time
|
||||||
*/
|
*/
|
||||||
public static SampleResult createTestSample(long start, long end) {
|
public static SampleResult createTestSample(long start, long end) {
|
||||||
|
@ -480,8 +507,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* Create a sample with a specific elapsed time for test purposes, but don't
|
* Create a sample with a specific elapsed time for test purposes, but don't
|
||||||
* allow the times to be changed later
|
* allow the times to be changed later
|
||||||
*
|
*
|
||||||
* @param elapsed
|
* @param elapsed - desired elapsed time in milliseconds
|
||||||
* - desired elapsed time in milliseconds
|
|
||||||
* @return sample that starts 'now' and ends <code>elapsed</code> milliseconds later
|
* @return sample that starts 'now' and ends <code>elapsed</code> milliseconds later
|
||||||
*/
|
*/
|
||||||
public static SampleResult createTestSample(long elapsed) {
|
public static SampleResult createTestSample(long elapsed) {
|
||||||
|
@ -497,9 +523,8 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* Helper method to get 1 ms resolution timing.
|
* Helper method to get 1 ms resolution timing.
|
||||||
*
|
*
|
||||||
* @return the current time in milliseconds
|
* @return the current time in milliseconds
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException when <code>useNanoTime</code> is <code>true</code> but
|
||||||
* when <code>useNanoTime</code> is <code>true</code> but
|
* <code>nanoTimeOffset</code> is not set
|
||||||
* <code>nanoTimeOffset</code> is not set
|
|
||||||
*/
|
*/
|
||||||
public long currentTimeInMillis() {
|
public long currentTimeInMillis() {
|
||||||
if (useNanoTime) {
|
if (useNanoTime) {
|
||||||
|
@ -527,13 +552,10 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* For use by SaveService only.
|
* For use by SaveService only.
|
||||||
*
|
*
|
||||||
* @param stamp
|
* @param stamp this may be a start time or an end time (both in milliseconds)
|
||||||
* this may be a start time or an end time (both in milliseconds)
|
* @param elapsed time in milliseconds
|
||||||
* @param elapsed
|
* @throws RuntimeException when <code>startTime</code> or <code>endTime</code> has been
|
||||||
* time in milliseconds
|
* set already
|
||||||
* @throws RuntimeException
|
|
||||||
* when <code>startTime</code> or <code>endTime</code> has been
|
|
||||||
* set already
|
|
||||||
*/
|
*/
|
||||||
public void setStampAndTime(long stamp, long elapsed) {
|
public void setStampAndTime(long stamp, long elapsed) {
|
||||||
if (startTime != 0 || endTime != 0) {
|
if (startTime != 0 || endTime != 0) {
|
||||||
|
@ -558,7 +580,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set response code to OK, i.e. "200"
|
* Set response code to OK, i.e. "200"
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void setResponseCodeOK() {
|
public void setResponseCodeOK() {
|
||||||
responseCode = OK_CODE;
|
responseCode = OK_CODE;
|
||||||
|
@ -609,10 +630,9 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Get the sample timestamp, which may be either the start time or the end time.
|
* Get the sample timestamp, which may be either the start time or the end time.
|
||||||
*
|
*
|
||||||
|
* @return timeStamp in milliseconds
|
||||||
* @see #getStartTime()
|
* @see #getStartTime()
|
||||||
* @see #getEndTime()
|
* @see #getEndTime()
|
||||||
*
|
|
||||||
* @return timeStamp in milliseconds
|
|
||||||
*/
|
*/
|
||||||
public long getTimeStamp() {
|
public long getTimeStamp() {
|
||||||
return timeStamp;
|
return timeStamp;
|
||||||
|
@ -652,7 +672,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* Gets the assertion results associated with this sample.
|
* Gets the assertion results associated with this sample.
|
||||||
*
|
*
|
||||||
* @return an array containing the assertion results for this sample.
|
* @return an array containing the assertion results for this sample.
|
||||||
* Returns empty array if there are no assertion results.
|
* Returns empty array if there are no assertion results.
|
||||||
*/
|
*/
|
||||||
public AssertionResult[] getAssertionResults() {
|
public AssertionResult[] getAssertionResults() {
|
||||||
if (assertionResults == null) {
|
if (assertionResults == null) {
|
||||||
|
@ -664,8 +684,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Add a subresult and adjust the parent byte count and end-time.
|
* Add a subresult and adjust the parent byte count and end-time.
|
||||||
*
|
*
|
||||||
* @param subResult
|
* @param subResult the {@link SampleResult} to be added
|
||||||
* the {@link SampleResult} to be added
|
|
||||||
*/
|
*/
|
||||||
public void addSubResult(SampleResult subResult) {
|
public void addSubResult(SampleResult subResult) {
|
||||||
addSubResult(subResult, isRenameSampleLabel());
|
addSubResult(subResult, isRenameSampleLabel());
|
||||||
|
@ -673,6 +692,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* see https://bz.apache.org/bugzilla/show_bug.cgi?id=63055
|
* see https://bz.apache.org/bugzilla/show_bug.cgi?id=63055
|
||||||
|
*
|
||||||
* @return true if TestPlan is in functional mode or property subresults.disable_renaming is true
|
* @return true if TestPlan is in functional mode or property subresults.disable_renaming is true
|
||||||
*/
|
*/
|
||||||
public static boolean isRenameSampleLabel() {
|
public static boolean isRenameSampleLabel() {
|
||||||
|
@ -682,8 +702,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Add a subresult and adjust the parent byte count and end-time.
|
* Add a subresult and adjust the parent byte count and end-time.
|
||||||
*
|
*
|
||||||
* @param subResult
|
* @param subResult the {@link SampleResult} to be added
|
||||||
* the {@link SampleResult} to be added
|
|
||||||
* @param renameSubResults boolean do we rename subResults based on position
|
* @param renameSubResults boolean do we rename subResults based on position
|
||||||
*/
|
*/
|
||||||
public void addSubResult(SampleResult subResult, boolean renameSubResults) {
|
public void addSubResult(SampleResult subResult, boolean renameSubResults) {
|
||||||
|
@ -711,8 +730,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Add a subresult to the collection without updating any parent fields.
|
* Add a subresult to the collection without updating any parent fields.
|
||||||
*
|
*
|
||||||
* @param subResult
|
* @param subResult the {@link SampleResult} to be added
|
||||||
* the {@link SampleResult} to be added
|
|
||||||
*/
|
*/
|
||||||
public void addRawSubResult(SampleResult subResult) {
|
public void addRawSubResult(SampleResult subResult) {
|
||||||
storeSubResult(subResult, isRenameSampleLabel());
|
storeSubResult(subResult, isRenameSampleLabel());
|
||||||
|
@ -721,8 +739,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Add a subresult to the collection without updating any parent fields.
|
* Add a subresult to the collection without updating any parent fields.
|
||||||
*
|
*
|
||||||
* @param subResult
|
* @param subResult the {@link SampleResult} to be added
|
||||||
* the {@link SampleResult} to be added
|
|
||||||
*/
|
*/
|
||||||
private void addRawSubResult(SampleResult subResult, boolean renameSubResults) {
|
private void addRawSubResult(SampleResult subResult, boolean renameSubResults) {
|
||||||
storeSubResult(subResult, renameSubResults);
|
storeSubResult(subResult, renameSubResults);
|
||||||
|
@ -735,8 +752,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* addSubResult(SampleResult)}, except that the fields don't need to be
|
* addSubResult(SampleResult)}, except that the fields don't need to be
|
||||||
* accumulated
|
* accumulated
|
||||||
*
|
*
|
||||||
* @param subResult
|
* @param subResult the {@link SampleResult} to be added
|
||||||
* the {@link SampleResult} to be added
|
|
||||||
*/
|
*/
|
||||||
public void storeSubResult(SampleResult subResult) {
|
public void storeSubResult(SampleResult subResult) {
|
||||||
storeSubResult(subResult, isRenameSampleLabel());
|
storeSubResult(subResult, isRenameSampleLabel());
|
||||||
|
@ -749,8 +765,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* addSubResult(SampleResult)}, except that the fields don't need to be
|
* addSubResult(SampleResult)}, except that the fields don't need to be
|
||||||
* accumulated
|
* accumulated
|
||||||
*
|
*
|
||||||
* @param subResult
|
* @param subResult the {@link SampleResult} to be added
|
||||||
* the {@link SampleResult} to be added
|
|
||||||
* @param renameSubResults boolean do we rename subResults based on position
|
* @param renameSubResults boolean do we rename subResults based on position
|
||||||
*/
|
*/
|
||||||
public void storeSubResult(SampleResult subResult, boolean renameSubResults) {
|
public void storeSubResult(SampleResult subResult, boolean renameSubResults) {
|
||||||
|
@ -768,7 +783,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* Gets the subresults associated with this sample.
|
* Gets the subresults associated with this sample.
|
||||||
*
|
*
|
||||||
* @return an array containing the subresults for this sample. Returns an
|
* @return an array containing the subresults for this sample. Returns an
|
||||||
* empty array if there are no subresults.
|
* empty array if there are no subresults.
|
||||||
*/
|
*/
|
||||||
public SampleResult[] getSubResults() {
|
public SampleResult[] getSubResults() {
|
||||||
if (subResults == null) {
|
if (subResults == null) {
|
||||||
|
@ -779,12 +794,11 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the responseData attribute of the SampleResult object.
|
* Sets the responseData attribute of the SampleResult object.
|
||||||
*
|
* <p>
|
||||||
* If the parameter is null, then the responseData is set to an empty byte array.
|
* If the parameter is null, then the responseData is set to an empty byte array.
|
||||||
* This ensures that getResponseData() can never be null.
|
* This ensures that getResponseData() can never be null.
|
||||||
*
|
*
|
||||||
* @param response
|
* @param response the new responseData value
|
||||||
* the new responseData value
|
|
||||||
*/
|
*/
|
||||||
public void setResponseData(byte[] response) {
|
public void setResponseData(byte[] response) {
|
||||||
responseDataAsString = null;
|
responseDataAsString = null;
|
||||||
|
@ -795,9 +809,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* Sets the responseData attribute of the SampleResult object.
|
* Sets the responseData attribute of the SampleResult object.
|
||||||
* Should only be called after setting the dataEncoding (if necessary)
|
* Should only be called after setting the dataEncoding (if necessary)
|
||||||
*
|
*
|
||||||
* @param response
|
* @param response the new responseData value (String)
|
||||||
* the new responseData value (String)
|
|
||||||
*
|
|
||||||
* @deprecated - only intended for use from BeanShell code
|
* @deprecated - only intended for use from BeanShell code
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -816,7 +828,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
*
|
*
|
||||||
* @param response the new responseData value (String)
|
* @param response the new responseData value (String)
|
||||||
* @param encoding the encoding to set and then use (if null, use platform default)
|
* @param encoding the encoding to set and then use (if null, use platform default)
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void setResponseData(final String response, final String encoding) {
|
public void setResponseData(final String response, final String encoding) {
|
||||||
responseDataAsString = null;
|
responseDataAsString = null;
|
||||||
|
@ -837,9 +848,10 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* <p>
|
* <p>
|
||||||
* Note that some samplers may not store all the data, in which case
|
* Note that some samplers may not store all the data, in which case
|
||||||
* getResponseData().length will be incorrect.
|
* getResponseData().length will be incorrect.
|
||||||
*
|
* <p>
|
||||||
* Instead, always use {@link #getBytes()} to obtain the sample result byte count.
|
* Instead, always use {@link #getBytes()} to obtain the sample result byte count.
|
||||||
* </p>
|
* </p>
|
||||||
|
*
|
||||||
* @return the responseData value (cannot be null)
|
* @return the responseData value (cannot be null)
|
||||||
*/
|
*/
|
||||||
public byte[] getResponseData() {
|
public byte[] getResponseData() {
|
||||||
|
@ -875,7 +887,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* Get the time it took this sample to occur.
|
* Get the time it took this sample to occur.
|
||||||
*
|
*
|
||||||
* @return elapsed time in milliseconds
|
* @return elapsed time in milliseconds
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public long getTime() {
|
public long getTime() {
|
||||||
return elapsedTime;
|
return elapsedTime;
|
||||||
|
@ -887,6 +898,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the data type of the sample.
|
* Sets the data type of the sample.
|
||||||
|
*
|
||||||
* @param dataType String containing {@link #BINARY} or {@link #TEXT}
|
* @param dataType String containing {@link #BINARY} or {@link #TEXT}
|
||||||
* @see #BINARY
|
* @see #BINARY
|
||||||
* @see #TEXT
|
* @see #TEXT
|
||||||
|
@ -909,9 +921,9 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Extract and save the DataEncoding and DataType from the parameter provided.
|
* Extract and save the DataEncoding and DataType from the parameter provided.
|
||||||
* Does not save the full content Type.
|
* Does not save the full content Type.
|
||||||
* @see #setContentType(String) which should be used to save the full content-type string
|
|
||||||
*
|
*
|
||||||
* @param ct - content type (may be null)
|
* @param ct - content type (may be null)
|
||||||
|
* @see #setContentType(String) which should be used to save the full content-type string
|
||||||
*/
|
*/
|
||||||
public void setEncodingAndType(String ct) {
|
public void setEncodingAndType(String ct) {
|
||||||
if (ct != null) {
|
if (ct != null) {
|
||||||
|
@ -966,8 +978,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Sets the successful attribute of the SampleResult object.
|
* Sets the successful attribute of the SampleResult object.
|
||||||
*
|
*
|
||||||
* @param success
|
* @param success the new successful value
|
||||||
* the new successful value
|
|
||||||
*/
|
*/
|
||||||
public void setSuccessful(boolean success) {
|
public void setSuccessful(boolean success) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
|
@ -1007,6 +1018,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the dataEncoding. May be null or the empty String.
|
* Returns the dataEncoding. May be null or the empty String.
|
||||||
|
*
|
||||||
* @return the value of the dataEncoding
|
* @return the value of the dataEncoding
|
||||||
*/
|
*/
|
||||||
public String getDataEncodingNoDefault() {
|
public String getDataEncodingNoDefault() {
|
||||||
|
@ -1016,8 +1028,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Sets the dataEncoding.
|
* Sets the dataEncoding.
|
||||||
*
|
*
|
||||||
* @param dataEncoding
|
* @param dataEncoding the dataEncoding to set, e.g. ISO-8895-1, UTF-8
|
||||||
* the dataEncoding to set, e.g. ISO-8895-1, UTF-8
|
|
||||||
*/
|
*/
|
||||||
public void setDataEncoding(String dataEncoding) {
|
public void setDataEncoding(String dataEncoding) {
|
||||||
this.dataEncoding = dataEncoding;
|
this.dataEncoding = dataEncoding;
|
||||||
|
@ -1072,7 +1083,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string -
|
* @param string -
|
||||||
* request headers
|
* request headers
|
||||||
*/
|
*/
|
||||||
public void setRequestHeaders(String string) {
|
public void setRequestHeaders(String string) {
|
||||||
requestHeaders = string;
|
requestHeaders = string;
|
||||||
|
@ -1080,7 +1091,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string -
|
* @param string -
|
||||||
* response headers
|
* response headers
|
||||||
*/
|
*/
|
||||||
public void setResponseHeaders(String string) {
|
public void setResponseHeaders(String string) {
|
||||||
responseHeaders = string;
|
responseHeaders = string;
|
||||||
|
@ -1095,6 +1106,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the media type from the Content Type
|
* Get the media type from the Content Type
|
||||||
|
*
|
||||||
* @return the media type - e.g. text/html (without charset, if any)
|
* @return the media type - e.g. text/html (without charset, if any)
|
||||||
*/
|
*/
|
||||||
public String getMediaType() {
|
public String getMediaType() {
|
||||||
|
@ -1103,9 +1115,9 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the content-type string, e.g. <code>text/xml; charset=utf-8</code>
|
* Stores the content-type string, e.g. <code>text/xml; charset=utf-8</code>
|
||||||
* @see #setEncodingAndType(String) which can be used to extract the charset.
|
|
||||||
*
|
*
|
||||||
* @param string the content-type to be set
|
* @param string the content-type to be set
|
||||||
|
* @see #setEncodingAndType(String) which can be used to extract the charset.
|
||||||
*/
|
*/
|
||||||
public void setContentType(String string) {
|
public void setContentType(String string) {
|
||||||
contentType = string;
|
contentType = string;
|
||||||
|
@ -1160,6 +1172,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Set idle time pause.
|
* Set idle time pause.
|
||||||
* For use by SampleResultConverter/CSVSaveService.
|
* For use by SampleResultConverter/CSVSaveService.
|
||||||
|
*
|
||||||
* @param idle long
|
* @param idle long
|
||||||
*/
|
*/
|
||||||
public void setIdleTime(long idle) {
|
public void setIdleTime(long idle) {
|
||||||
|
@ -1173,7 +1186,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record the start time of a sample
|
* Record the start time of a sample
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void sampleStart() {
|
public void sampleStart() {
|
||||||
if (startTime == 0) {
|
if (startTime == 0) {
|
||||||
|
@ -1185,7 +1197,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record the end time of a sample and calculate the elapsed time
|
* Record the end time of a sample and calculate the elapsed time
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void sampleEnd() {
|
public void sampleEnd() {
|
||||||
if (endTime == 0) {
|
if (endTime == 0) {
|
||||||
|
@ -1197,7 +1208,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause a sample
|
* Pause a sample
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void samplePause() {
|
public void samplePause() {
|
||||||
if (pauseTime != 0) {
|
if (pauseTime != 0) {
|
||||||
|
@ -1208,7 +1218,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume a sample
|
* Resume a sample
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void sampleResume() {
|
public void sampleResume() {
|
||||||
if (pauseTime == 0) {
|
if (pauseTime == 0) {
|
||||||
|
@ -1221,9 +1230,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* When a Sampler is working as a monitor
|
* When a Sampler is working as a monitor
|
||||||
*
|
*
|
||||||
* @param monitor
|
* @param monitor flag whether this sampler is working as a monitor
|
||||||
* flag whether this sampler is working as a monitor
|
|
||||||
*
|
|
||||||
* @deprecated since 3.2 NOOP
|
* @deprecated since 3.2 NOOP
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -1265,7 +1272,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* Returns the count of errors.
|
* Returns the count of errors.
|
||||||
*
|
*
|
||||||
* @return 0 - or 1 if the sample failed
|
* @return 0 - or 1 if the sample failed
|
||||||
*
|
* <p>
|
||||||
* TODO do we need allow for nested samples?
|
* TODO do we need allow for nested samples?
|
||||||
*/
|
*/
|
||||||
public int getErrorCount() {
|
public int getErrorCount() {
|
||||||
|
@ -1299,8 +1306,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* still want to calculate the throughput. The bytes are the bytes of the
|
* still want to calculate the throughput. The bytes are the bytes of the
|
||||||
* response data.
|
* response data.
|
||||||
*
|
*
|
||||||
* @param length
|
* @param length the number of bytes of the response data for this sample
|
||||||
* the number of bytes of the response data for this sample
|
|
||||||
*/
|
*/
|
||||||
public void setBytes(long length) {
|
public void setBytes(long length) {
|
||||||
bytes = length;
|
bytes = length;
|
||||||
|
@ -1311,8 +1317,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
* still want to calculate the throughput. The bytes are the bytes of the
|
* still want to calculate the throughput. The bytes are the bytes of the
|
||||||
* response data.
|
* response data.
|
||||||
*
|
*
|
||||||
* @param length
|
* @param length the number of bytes of the response data for this sample
|
||||||
* the number of bytes of the response data for this sample
|
|
||||||
* @deprecated use setBytes(long)
|
* @deprecated use setBytes(long)
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -1321,7 +1326,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param sentBytesCount long sent bytes
|
* @param sentBytesCount long sent bytes
|
||||||
*/
|
*/
|
||||||
public void setSentBytes(long sentBytesCount) {
|
public void setSentBytes(long sentBytesCount) {
|
||||||
|
@ -1365,7 +1369,6 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the time to the first response
|
* Set the time to the first response
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void latencyEnd() {
|
public void latencyEnd() {
|
||||||
latency = currentTimeInMillis() - startTime - idleTime;
|
latency = currentTimeInMillis() - startTime - idleTime;
|
||||||
|
@ -1374,8 +1377,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* This is only intended for use by SampleResultConverter!
|
* This is only intended for use by SampleResultConverter!
|
||||||
*
|
*
|
||||||
* @param latency
|
* @param latency The latency to set.
|
||||||
* The latency to set.
|
|
||||||
*/
|
*/
|
||||||
public void setLatency(long latency) {
|
public void setLatency(long latency) {
|
||||||
this.latency = latency;
|
this.latency = latency;
|
||||||
|
@ -1407,8 +1409,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* This is only intended for use by SampleResultConverter!
|
* This is only intended for use by SampleResultConverter!
|
||||||
*
|
*
|
||||||
* @param timeStamp
|
* @param timeStamp The timeStamp to set.
|
||||||
* The timeStamp to set.
|
|
||||||
*/
|
*/
|
||||||
public void setTimeStamp(long timeStamp) {
|
public void setTimeStamp(long timeStamp) {
|
||||||
this.timeStamp = timeStamp;
|
this.timeStamp = timeStamp;
|
||||||
|
@ -1440,8 +1441,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parent
|
* @param parent The parent to set.
|
||||||
* The parent to set.
|
|
||||||
*/
|
*/
|
||||||
public void setParent(SampleResult parent) {
|
public void setParent(SampleResult parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
@ -1472,6 +1472,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bug 47394
|
// Bug 47394
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow custom SampleSenders to drop unwanted assertionResults
|
* Allow custom SampleSenders to drop unwanted assertionResults
|
||||||
*/
|
*/
|
||||||
|
@ -1489,8 +1490,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
/**
|
/**
|
||||||
* Set the headers size in bytes
|
* Set the headers size in bytes
|
||||||
*
|
*
|
||||||
* @param size
|
* @param size the number of bytes of the header
|
||||||
* the number of bytes of the header
|
|
||||||
*/
|
*/
|
||||||
public void setHeadersSize(int size) {
|
public void setHeadersSize(int size) {
|
||||||
this.headersSize = size;
|
this.headersSize = size;
|
||||||
|
@ -1549,7 +1549,7 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
public void run() {
|
public void run() {
|
||||||
// Wait longer than a clock pulse (generally 10-15ms)
|
// Wait longer than a clock pulse (generally 10-15ms)
|
||||||
getOffset(30L); // Catch an early clock pulse to reduce slop.
|
getOffset(30L); // Catch an early clock pulse to reduce slop.
|
||||||
while(true) {
|
while (true) {
|
||||||
getOffset(NANOTHREAD_SLEEP); // Can now afford to wait a bit longer between checks
|
getOffset(NANOTHREAD_SLEEP); // Can now afford to wait a bit longer between checks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1577,12 +1577,12 @@ public class SampleResult implements Serializable, Cloneable, Searchable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use SampleResult#setTestLogicalAction(TestLogicalAction)
|
|
||||||
* @param startNextThreadLoop the startNextLoop to set
|
* @param startNextThreadLoop the startNextLoop to set
|
||||||
|
* @deprecated use SampleResult#setTestLogicalAction(TestLogicalAction)
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setStartNextThreadLoop(boolean startNextThreadLoop) {
|
public void setStartNextThreadLoop(boolean startNextThreadLoop) {
|
||||||
if(startNextThreadLoop) {
|
if (startNextThreadLoop) {
|
||||||
testLogicalAction = TestLogicalAction.START_NEXT_ITERATION_OF_THREAD;
|
testLogicalAction = TestLogicalAction.START_NEXT_ITERATION_OF_THREAD;
|
||||||
} else {
|
} else {
|
||||||
testLogicalAction = TestLogicalAction.CONTINUE;
|
testLogicalAction = TestLogicalAction.CONTINUE;
|
||||||
|
|
Loading…
Reference in New Issue