diff --git a/arex-schedule-web-api/pom.xml b/arex-schedule-web-api/pom.xml
index 6b22de85..c22564f1 100644
--- a/arex-schedule-web-api/pom.xml
+++ b/arex-schedule-web-api/pom.xml
@@ -136,7 +136,7 @@
arex-schedule-parent
com.arextest
- 1.2.17
+ 1.2.18
@@ -338,5 +338,5 @@
- 1.2.17
+ 1.2.18
\ No newline at end of file
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/HttpWepServiceApiClient.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/HttpWepServiceApiClient.java
index 3e70cbff..c2aa2782 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/HttpWepServiceApiClient.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/HttpWepServiceApiClient.java
@@ -1,6 +1,7 @@
package com.arextest.schedule.client;
import static com.arextest.schedule.common.CommonConstant.URL;
+import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import com.arextest.schedule.utils.SSLUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -74,6 +75,7 @@ public final class HttpWepServiceApiClient {
@Autowired(required = false)
private List clientHttpRequestInterceptors;
+ private static final String ZSTD_JSON_CONTENT_TYPE = "application/zstd-json;charset=UTF-8";
@PostConstruct
private void initTemplate() {
@@ -250,6 +252,21 @@ public ResponseEntity retryJsonPost(String url,
}
}
+ public TResponse retryZstdJsonPost(String url, TRequest request,
+ Class responseType) {
+ Map headers = Maps.newHashMapWithExpectedSize(1);
+ headers.put(HttpHeaders.CONTENT_TYPE, ZSTD_JSON_CONTENT_TYPE);
+
+ try {
+ return retryTemplate.execute(retryCallback -> {
+ retryCallback.setAttribute(URL, url);
+ return restTemplate.postForObject(url, wrapJsonContentType(request, headers), responseType);
+ });
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
@SuppressWarnings("unchecked")
private HttpEntity wrapJsonContentType(TRequest request) {
HttpEntity httpJsonEntity;
@@ -271,7 +288,9 @@ private HttpEntity wrapJsonContentType(TRequest request,
httpJsonEntity = (HttpEntity) request;
} else {
HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_JSON);
+ if (!extraHeaders.containsKey(CONTENT_TYPE)) {
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ }
headers.setAll(extraHeaders);
httpJsonEntity = new HttpEntity<>(request, headers);
}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/ZstdJacksonMessageConverter.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/ZstdJacksonMessageConverter.java
index 4c4cb7ce..5db1b764 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/ZstdJacksonMessageConverter.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/client/ZstdJacksonMessageConverter.java
@@ -29,7 +29,7 @@ public ZstdJacksonMessageConverter() {
@Override
protected boolean supports(Class> clazz) {
- return true;
+ return !(clazz == byte[].class || clazz.isPrimitive());
}
@Override
@@ -41,6 +41,6 @@ protected Object readInternal(Class> clazz, HttpInputMessage inputMessage) thr
@Override
protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException,
HttpMessageNotWritableException {
- zstdJacksonSerializer.serializeTo(o, outputMessage.getBody());
+ outputMessage.getBody().write(zstdJacksonSerializer.serialize(o));
}
}
\ No newline at end of file
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/common/JsonUtils.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/common/JsonUtils.java
index f9f9ede4..04f248bf 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/common/JsonUtils.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/common/JsonUtils.java
@@ -22,11 +22,20 @@ public static T byteToObject(byte[] bytes, Class tClass) {
return null;
}
+ public static T jsonStringToObject(String string, Class tClass) {
+ try {
+ return objectMapper.readValue(string, tClass);
+ } catch (IOException e) {
+ LOGGER.error("jsonStringToObject error:{}", e.getMessage(), e);
+ }
+ return null;
+ }
+
public static String objectToJsonString(Object value) {
try {
return objectMapper.writeValueAsString(value);
} catch (IOException e) {
- LOGGER.error("byteToObject error:{}", e.getMessage(), e);
+ LOGGER.error("objectToJsonString error:{}", e.getMessage(), e);
}
return StringUtils.EMPTY;
}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/CategoryComparisonHolder.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/CategoryComparisonHolder.java
index 17a1b2b8..80317ddb 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/CategoryComparisonHolder.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/CategoryComparisonHolder.java
@@ -1,6 +1,7 @@
package com.arextest.schedule.comparer;
import java.util.List;
+import lombok.AllArgsConstructor;
import lombok.Data;
/**
@@ -11,6 +12,22 @@
public class CategoryComparisonHolder {
private String categoryName;
+ /**
+ * Need to match the comparison relationship
+ */
private List record;
private List replayResult;
+
+ private boolean needMatch;
+ /**
+ * Not need to match the comparison relationship
+ */
+ private CompareResultItem compareResultItem;
+
+ @Data
+ @AllArgsConstructor
+ public static class CompareResultItem {
+ CompareItem recordItem;
+ CompareItem replayItem;
+ }
}
\ No newline at end of file
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/CompareItemConvertFactory.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/CompareItemConvertFactory.java
new file mode 100644
index 00000000..4970683d
--- /dev/null
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/CompareItemConvertFactory.java
@@ -0,0 +1,26 @@
+package com.arextest.schedule.comparer.converter;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import javax.annotation.Resource;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CompareItemConvertFactory {
+ private final Map categoryConverters;
+ @Resource
+ private CompareItemConverter defaultCompareItemConverterImpl;
+
+ public CompareItemConvertFactory(@Autowired List converters) {
+ this.categoryConverters = converters.stream().filter(c -> StringUtils.isNotBlank(c.getCategoryName()))
+ .collect(Collectors.toMap(CompareItemConverter::getCategoryName, Function.identity()));
+ }
+
+ public CompareItemConverter getConvert(String categoryName) {
+ return categoryConverters.getOrDefault(categoryName, defaultCompareItemConverterImpl);
+ }
+}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/CompareItemConverter.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/CompareItemConverter.java
new file mode 100644
index 00000000..e872bf30
--- /dev/null
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/CompareItemConverter.java
@@ -0,0 +1,29 @@
+package com.arextest.schedule.comparer.converter;
+
+import com.arextest.model.mock.AREXMocker;
+import com.arextest.model.replay.CompareRelationResult;
+import com.arextest.schedule.comparer.CompareItem;
+
+public interface CompareItemConverter {
+ String DEFAULT_CATEGORY_NAME = "default";
+
+ default String getCategoryName() {
+ return DEFAULT_CATEGORY_NAME;
+ }
+
+ /**
+ * Convert mocker to compare item, The agent handles the compatibility needs before the match
+ * @param mocker
+ * @return
+ */
+ CompareItem convert(AREXMocker mocker);
+
+ /**
+ * Convert relation result to compare item
+ * @param relationResult
+ * @param recordCompareItem
+ * @return
+ */
+ CompareItem convert(CompareRelationResult relationResult, boolean recordCompareItem);
+
+}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/DatabaseCompareItemConverterImpl.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/DatabaseCompareItemConverterImpl.java
new file mode 100644
index 00000000..d01f33b2
--- /dev/null
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/DatabaseCompareItemConverterImpl.java
@@ -0,0 +1,92 @@
+package com.arextest.schedule.comparer.converter.impl;
+
+import com.arextest.model.constants.MockAttributeNames;
+import com.arextest.model.mock.AREXMocker;
+import com.arextest.model.mock.MockCategoryType;
+import com.arextest.model.mock.Mocker.Target;
+import com.arextest.model.replay.CompareRelationResult;
+import com.arextest.schedule.common.JsonUtils;
+import com.arextest.schedule.comparer.CompareItem;
+import com.arextest.schedule.comparer.converter.CompareItemConverter;
+import com.arextest.schedule.comparer.impl.PrepareCompareItemBuilder.CompareItemImpl;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.Map;
+import java.util.Map.Entry;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author xinyuan_wang.
+ * @create 2024/9/2 16:46
+ */
+@Slf4j
+@Component
+public class DatabaseCompareItemConverterImpl implements CompareItemConverter {
+
+ @Override
+ public String getCategoryName() {
+ return MockCategoryType.DATABASE.getName();
+ }
+
+ @Override
+ public CompareItem convert(AREXMocker mocker) {
+ MockCategoryType categoryType = mocker.getCategoryType();
+ String operationKey = getOperationName(mocker.getTargetRequest(), mocker.getOperationName());
+ return new CompareItemImpl(operationKey, buildAttributes(mocker.getTargetRequest()).toString(),
+ mocker.getId(), mocker.getCreationTime(), categoryType.isEntryPoint());
+ }
+
+ @Override
+ public CompareItem convert(CompareRelationResult relationResult, boolean recordCompareItem) {
+ String message = recordCompareItem ? relationResult.getRecordMessage() : relationResult.getReplayMessage();
+ long createTime = recordCompareItem ? relationResult.getRecordTime() : relationResult.getReplayTime();
+ return new CompareItemImpl(relationResult.getOperationName(), processMessage(message), null,
+ createTime, relationResult.getCategoryType().isEntryPoint());
+ }
+
+ private String processMessage(String message) {
+ if (StringUtils.isBlank(message)) {
+ return message;
+ }
+
+ Target target = JsonUtils.jsonStringToObject(message, Target.class);
+ if (target != null) {
+ message = buildAttributes(target).toString();
+ }
+ return message;
+ }
+
+ private ObjectNode buildAttributes(Target target) {
+ ObjectNode obj = JsonNodeFactory.instance.objectNode();
+ if (target == null) {
+ return obj;
+ }
+ Map attributes = target.getAttributes();
+ if (attributes != null) {
+ for (Entry entry : attributes.entrySet()) {
+ Object value = entry.getValue();
+ if (value instanceof String) {
+ obj.put(entry.getKey(), (String) value);
+ } else {
+ obj.putPOJO(entry.getKey(), value);
+ }
+ }
+ }
+ if (StringUtils.isNotEmpty(target.getBody())) {
+ obj.put("body", target.getBody());
+ }
+ return obj;
+ }
+
+ private String getOperationName(Target target, String operationName) {
+ // The "@" in the operationName of DATABASE indicates that the SQL statement has been parsed and returned directly.
+ String compareOperationName = StringUtils.contains(operationName, "@") ? operationName
+ : target.attributeAsString(MockAttributeNames.DB_NAME);
+ if (StringUtils.isNotBlank(compareOperationName)) {
+ return compareOperationName;
+ }
+ return operationName;
+ }
+}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/DefaultCompareItemConverterImpl.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/DefaultCompareItemConverterImpl.java
new file mode 100644
index 00000000..fbd1c731
--- /dev/null
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/DefaultCompareItemConverterImpl.java
@@ -0,0 +1,46 @@
+package com.arextest.schedule.comparer.converter.impl;
+
+import com.arextest.model.mock.AREXMocker;
+import com.arextest.model.mock.MockCategoryType;
+import com.arextest.model.replay.CompareRelationResult;
+import com.arextest.schedule.comparer.CompareItem;
+import com.arextest.schedule.comparer.converter.CompareItemConverter;
+import com.arextest.schedule.comparer.impl.PrepareCompareItemBuilder.CompareItemImpl;
+import java.util.Objects;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author xinyuan_wang.
+ * @create 2024/9/2 16:46
+ */
+@Slf4j
+@Component
+public class DefaultCompareItemConverterImpl implements CompareItemConverter {
+
+ @Override
+ public CompareItem convert(AREXMocker mocker) {
+ MockCategoryType categoryType = mocker.getCategoryType();
+ String operationKey = mocker.getOperationName();
+ long createTime = mocker.getCreationTime();
+ String body;
+ String compareKey = mocker.getId();
+ boolean entryPointCategory = false;
+ if (categoryType.isEntryPoint()) {
+ body = Objects.isNull(mocker.getTargetResponse()) ? null
+ : mocker.getTargetResponse().getBody();
+ compareKey = null;
+ entryPointCategory = true;
+ } else {
+ body = Objects.isNull(mocker.getTargetRequest()) ? null
+ : mocker.getTargetRequest().getBody();
+ }
+ return new CompareItemImpl(operationKey, body, compareKey, createTime, entryPointCategory);
+ }
+
+ @Override
+ public CompareItem convert(CompareRelationResult relationResult, boolean recordCompareItem) {
+ return new CompareItemImpl(relationResult, recordCompareItem);
+ }
+
+}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/RedisCompareItemConverterImpl.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/RedisCompareItemConverterImpl.java
new file mode 100644
index 00000000..9bf0c0ad
--- /dev/null
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/converter/impl/RedisCompareItemConverterImpl.java
@@ -0,0 +1,54 @@
+package com.arextest.schedule.comparer.converter.impl;
+
+import com.arextest.model.constants.MockAttributeNames;
+import com.arextest.model.mock.AREXMocker;
+import com.arextest.model.mock.MockCategoryType;
+import com.arextest.model.mock.Mocker.Target;
+import com.arextest.model.replay.CompareRelationResult;
+import com.arextest.schedule.comparer.CompareItem;
+import com.arextest.schedule.comparer.converter.CompareItemConverter;
+import com.arextest.schedule.comparer.impl.PrepareCompareItemBuilder.CompareItemImpl;
+import java.util.Objects;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author xinyuan_wang.
+ * @create 2024/9/2 16:46
+ */
+@Slf4j
+@Component
+public class RedisCompareItemConverterImpl implements CompareItemConverter {
+
+ @Override
+ public String getCategoryName() {
+ return MockCategoryType.REDIS.getName();
+ }
+
+ @Override
+ public CompareItem convert(AREXMocker mocker) {
+ MockCategoryType categoryType = mocker.getCategoryType();
+ String operationKey = getOperationName(mocker.getTargetRequest(), mocker.getOperationName());
+ String compareMessage = Objects.isNull(mocker.getTargetRequest()) ? null
+ : mocker.getTargetRequest().getBody();
+
+ return new CompareItemImpl(operationKey, compareMessage, mocker.getId(),
+ mocker.getCreationTime(), categoryType.isEntryPoint());
+ }
+ @Override
+ public CompareItem convert(CompareRelationResult relationResult, boolean recordCompareItem) {
+ String message = recordCompareItem ? relationResult.getRecordMessage() : relationResult.getReplayMessage();
+ long createTime = recordCompareItem ? relationResult.getRecordTime() : relationResult.getReplayTime();
+ return new CompareItemImpl(relationResult.getOperationName(), message, null,
+ createTime, relationResult.getCategoryType().isEntryPoint());
+ }
+
+ private String getOperationName(Target target, String operationName) {
+ String compareOperationName = target.attributeAsString(MockAttributeNames.CLUSTER_NAME);
+ if (StringUtils.isNotBlank(compareOperationName)) {
+ return compareOperationName;
+ }
+ return operationName;
+ }
+}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/DefaultReplayResultComparer.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/DefaultReplayResultComparer.java
index 9adba651..90791b15 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/DefaultReplayResultComparer.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/DefaultReplayResultComparer.java
@@ -6,6 +6,7 @@
import com.arextest.diff.sdk.CompareSDK;
import com.arextest.model.mock.MockCategoryType;
import com.arextest.schedule.comparer.CategoryComparisonHolder;
+import com.arextest.schedule.comparer.CategoryComparisonHolder.CompareResultItem;
import com.arextest.schedule.comparer.CompareConfigService;
import com.arextest.schedule.comparer.CompareItem;
import com.arextest.schedule.comparer.CompareService;
@@ -162,10 +163,39 @@ public List doContentCompare(ReplayActionCaseItem caseItem,
}
/**
- * compare recording and replay data. 1. record and replay data through compareKey.
+ * compare recording and replay data.
*/
private List compareReplayResult(CategoryComparisonHolder bindHolder,
ReplayActionCaseItem caseItem, ComparisonInterfaceConfig operationConfig) {
+ if (bindHolder.isNeedMatch()) {
+ return matchCompareReplayResults(bindHolder, caseItem, operationConfig);
+ }
+
+ return getReplayCompareResults(bindHolder, caseItem, operationConfig);
+ }
+
+ private List getReplayCompareResults(CategoryComparisonHolder bindHolder,
+ ReplayActionCaseItem caseItem, ComparisonInterfaceConfig operationConfig) {
+ CompareResultItem item = bindHolder.getCompareResultItem();
+ if (item == null) {
+ return Collections.emptyList();
+ }
+
+ List compareResults = new ArrayList<>();
+ compareResults.add(compareRecordAndResult(operationConfig, caseItem, bindHolder.getCategoryName(),
+ item.getReplayItem(), item.getRecordItem()));
+ return compareResults;
+ }
+
+ /**
+ * record and replay data through compareKey.
+ * @param bindHolder
+ * @param caseItem
+ * @param operationConfig
+ * @return
+ */
+ private List matchCompareReplayResults(CategoryComparisonHolder bindHolder,
+ ReplayActionCaseItem caseItem, ComparisonInterfaceConfig operationConfig) {
List compareResults = new ArrayList<>();
List recordResults = bindHolder.getRecord();
List replayResults = bindHolder.getReplayResult();
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareItemBuilder.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareItemBuilder.java
index c918dbbc..5d679208 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareItemBuilder.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareItemBuilder.java
@@ -1,16 +1,11 @@
package com.arextest.schedule.comparer.impl;
-import com.arextest.model.constants.MockAttributeNames;
import com.arextest.model.mock.AREXMocker;
-import com.arextest.model.mock.MockCategoryType;
-import com.arextest.model.mock.Mocker.Target;
+import com.arextest.model.replay.CompareRelationResult;
import com.arextest.schedule.comparer.CompareItem;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import org.apache.commons.lang3.StringUtils;
+import com.arextest.schedule.comparer.converter.CompareItemConvertFactory;
+import com.arextest.schedule.comparer.converter.CompareItemConverter;
+import javax.annotation.Resource;
import org.springframework.stereotype.Component;
/**
@@ -18,67 +13,22 @@
* @since 2021/11/23
*/
@Component
-final class PrepareCompareItemBuilder {
+public class PrepareCompareItemBuilder {
- CompareItem build(AREXMocker instance) {
- MockCategoryType categoryType = instance.getCategoryType();
- String operationKey = operationName(categoryType, instance.getTargetRequest(), instance.getOperationName());
- if (StringUtils.isEmpty(operationKey)) {
- operationKey = instance.getOperationName();
- }
- long createTime = instance.getCreationTime();
- String body;
- String compareKey = instance.getId();
- boolean entryPointCategory = false;
- if (categoryType.isEntryPoint()) {
- body = Objects.isNull(instance.getTargetResponse()) ? null
- : instance.getTargetResponse().getBody();
- compareKey = null;
- entryPointCategory = true;
- } else if (Objects.equals(categoryType.getName(), MockCategoryType.DATABASE.getName())) {
- body = this.buildAttributes(instance.getTargetRequest()).toString();
- } else {
- body = Objects.isNull(instance.getTargetRequest()) ? null
- : instance.getTargetRequest().getBody();
- }
- return new CompareItemImpl(operationKey, body, compareKey, createTime, entryPointCategory);
- }
+ @Resource
+ private CompareItemConvertFactory factory;
- private String operationName(MockCategoryType categoryType, Target target, String operationName) {
- if (Objects.equals(categoryType, MockCategoryType.DATABASE)) {
- // The "@" in the operationName of DATABASE indicates that the SQL statement has been parsed and returned directly.
- return StringUtils.contains(operationName, "@") ? operationName : target.attributeAsString(MockAttributeNames.DB_NAME);
- }
- if (Objects.equals(categoryType, MockCategoryType.REDIS)) {
- return target.attributeAsString(MockAttributeNames.CLUSTER_NAME);
- }
- return operationName;
+ CompareItem build(AREXMocker mocker) {
+ CompareItemConverter converter = factory.getConvert(mocker.getCategoryType().getName());
+ return converter.convert(mocker);
}
- private ObjectNode buildAttributes(Target target) {
- ObjectNode obj = JsonNodeFactory.instance.objectNode();
- if (target == null) {
- return obj;
- }
- Map attributes = target.getAttributes();
- if (attributes != null) {
- for (Entry entry : attributes.entrySet()) {
- Object value = entry.getValue();
- if (value instanceof String) {
- obj.put(entry.getKey(), (String) value);
- } else {
- obj.putPOJO(entry.getKey(), value);
- }
- }
- }
- if (StringUtils.isNotEmpty(target.getBody())) {
- obj.put("body", target.getBody());
- }
- return obj;
+ public CompareItem build(CompareRelationResult result, boolean recordCompareItem) {
+ CompareItemConverter converter = factory.getConvert(result.getCategoryType().getName());
+ return converter.convert(result, recordCompareItem);
}
- private final static class CompareItemImpl implements CompareItem {
-
+ public final static class CompareItemImpl implements CompareItem {
private final String compareMessage;
private final String compareOperation;
private final String compareService;
@@ -86,11 +36,20 @@ private final static class CompareItemImpl implements CompareItem {
private final long createTime;
private final boolean entryPointCategory;
- private CompareItemImpl(String compareOperation, String compareMessage, String compareKey,
+ public CompareItemImpl(String compareOperation, String compareMessage, String compareKey,
long createTime, boolean entryPointCategory) {
this(compareOperation, compareMessage, null, compareKey, createTime, entryPointCategory);
}
+ public CompareItemImpl(CompareRelationResult result, boolean recordCompareItem) {
+ this.compareOperation = result.getOperationName();
+ this.compareService = null;
+ this.compareKey = null;
+ this.entryPointCategory = result.getCategoryType().isEntryPoint();
+ this.compareMessage = recordCompareItem ? result.getRecordMessage() : result.getReplayMessage();
+ this.createTime = recordCompareItem ? result.getRecordTime() : result.getReplayTime();
+ }
+
private CompareItemImpl(String compareOperation, String compareMessage, String compareService,
String compareKey,
long createTime, boolean entryPointCategory) {
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareSourceRemoteLoader.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareSourceRemoteLoader.java
index 844743bc..d128e8b5 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareSourceRemoteLoader.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/comparer/impl/PrepareCompareSourceRemoteLoader.java
@@ -1,13 +1,14 @@
package com.arextest.schedule.comparer.impl;
+import com.arextest.model.replay.CompareRelationResult;
import com.arextest.model.mock.AREXMocker;
import com.arextest.model.mock.MockCategoryType;
import com.arextest.model.replay.QueryReplayResultRequestType;
import com.arextest.model.replay.QueryReplayResultResponseType;
import com.arextest.model.replay.holder.ListResultHolder;
-import com.arextest.model.response.ResponseStatusType;
import com.arextest.schedule.client.HttpWepServiceApiClient;
import com.arextest.schedule.comparer.CategoryComparisonHolder;
+import com.arextest.schedule.comparer.CategoryComparisonHolder.CompareResultItem;
import com.arextest.schedule.comparer.CompareItem;
import com.arextest.schedule.model.ReplayActionCaseItem;
import com.arextest.schedule.serialization.ZstdJacksonSerializer;
@@ -78,38 +79,46 @@ private QueryReplayResultResponseType remoteLoad(String replayId, String resultI
QueryReplayResultRequestType resultRequest = new QueryReplayResultRequestType();
resultRequest.setRecordId(replayId);
resultRequest.setReplayResultId(resultId);
- return httpWepServiceApiClient.retryJsonPost(replayResultUrl, resultRequest,
- QueryReplayResultResponseType.class);
+ return httpWepServiceApiClient.retryZstdJsonPost(replayResultUrl,
+ resultRequest, QueryReplayResultResponseType.class);
}
+ /**
+ * Compatible logic.
+ * The subsequent agent will match the packets and does not need to be processed in the schedule.
+ * @param replayResultResponseType
+ * @return
+ */
private List decodeResult(
QueryReplayResultResponseType replayResultResponseType) {
- if (replayResultResponseType == null) {
+ if (replayResultResponseType == null ||
+ replayResultResponseType.getResponseStatusType() == null ||
+ replayResultResponseType.getResponseStatusType().hasError() ||
+ Boolean.TRUE.equals(replayResultResponseType.getInvalidResult())) {
+ LOGGER.warn("failed to get replay result because of invalid case");
return Collections.emptyList();
}
- ResponseStatusType responseStatusType = replayResultResponseType.getResponseStatusType();
- if (responseStatusType == null) {
- return Collections.emptyList();
- }
- if (responseStatusType.hasError()) {
- LOGGER.warn("query replay result has error response : {}", responseStatusType);
- return Collections.emptyList();
- }
- if (Boolean.TRUE.equals(replayResultResponseType.getInvalidResult())) {
- LOGGER.warn("query replay result has invalid result: get data failed from storage");
- return Collections.emptyList();
- }
+
+ // Use needMatch to determine whether to adopt new logic
+ return Boolean.TRUE.equals(replayResultResponseType.getNeedMatch()) ?
+ processMatchNeeded(replayResultResponseType) : processMatchNotNeeded(replayResultResponseType);
+ }
+
+ /**
+ * Processing of messages that require matching relationships that need to be compared
+ * @param replayResultResponseType
+ * @return
+ */
+ private List processMatchNeeded(QueryReplayResultResponseType replayResultResponseType) {
List resultHolderList = replayResultResponseType.getResultHolderList();
if (CollectionUtils.isEmpty(resultHolderList)) {
LOGGER.warn("query replay result has empty size");
return Collections.emptyList();
}
- List decodedListResult = new ArrayList<>(resultHolderList.size());
- MockCategoryType categoryType;
- for (int i = 0; i < resultHolderList.size(); i++) {
- ListResultHolder stringListResultHolder = resultHolderList.get(i);
- categoryType = stringListResultHolder.getCategoryType();
+ List decodedListResult = new ArrayList<>(resultHolderList.size());
+ for (ListResultHolder stringListResultHolder : resultHolderList) {
+ MockCategoryType categoryType = stringListResultHolder.getCategoryType();
if (categoryType == null || categoryType.isSkipComparison()) {
continue;
}
@@ -117,19 +126,56 @@ private List decodeResult(
CategoryComparisonHolder resultHolder = new CategoryComparisonHolder();
resultHolder.setCategoryName(categoryType.getName());
decodedListResult.add(resultHolder);
+
List recordList = zstdDeserialize(stringListResultHolder.getRecord());
- List replayResultList = zstdDeserialize(
- stringListResultHolder.getReplayResult());
- if (categoryType.isEntryPoint()) {
- boolean recordEmpty = CollectionUtils.isEmpty(recordList);
- boolean replayResultEmpty = CollectionUtils.isEmpty(replayResultList);
+ List replayResultList = zstdDeserialize(stringListResultHolder.getReplayResult());
+
+ if (categoryType.isEntryPoint() && (CollectionUtils.isEmpty(recordList) || CollectionUtils.isEmpty(replayResultList))) {
// call missing or new call
- if (recordEmpty || replayResultEmpty) {
- return Collections.emptyList();
- }
+ return Collections.emptyList();
}
+
resultHolder.setRecord(recordList);
resultHolder.setReplayResult(replayResultList);
+ resultHolder.setNeedMatch(true);
+ }
+ return decodedListResult;
+ }
+
+ /**
+ * Processing of packets that do not require matching
+ * @param replayResultResponseType
+ * @return
+ */
+ private List processMatchNotNeeded(QueryReplayResultResponseType replayResultResponseType) {
+ List replayResults = replayResultResponseType.getReplayResults();
+ if (CollectionUtils.isEmpty(replayResults)) {
+ LOGGER.warn("query replay result has empty size");
+ return Collections.emptyList();
+ }
+
+ List decodedListResult = new ArrayList<>(replayResults.size());
+ for (CompareRelationResult result : replayResults) {
+ MockCategoryType categoryType = result.getCategoryType();
+ if (categoryType == null || (!categoryType.isEntryPoint() && categoryType.isSkipComparison())) {
+ continue;
+ }
+
+ if (categoryType.isEntryPoint() && !categoryType.isSkipComparison() &&
+ (StringUtils.isEmpty(result.getRecordMessage()) || StringUtils.isEmpty(result.getReplayMessage()))) {
+ // The main category is missing
+ return Collections.emptyList();
+ }
+
+ CategoryComparisonHolder resultHolder = new CategoryComparisonHolder();
+ resultHolder.setCategoryName(categoryType.getName());
+
+ CompareItem recordCompareItem = prepareCompareItemBuilder.build(result, true);
+ CompareItem replayCompareItem = prepareCompareItemBuilder.build(result, false);
+
+ resultHolder.setCompareResultItem(new CompareResultItem(recordCompareItem, replayCompareItem));
+ resultHolder.setNeedMatch(false);
+ decodedListResult.add(resultHolder);
}
return decodedListResult;
}
diff --git a/arex-schedule-web-api/src/main/java/com/arextest/schedule/serialization/ZstdJacksonSerializer.java b/arex-schedule-web-api/src/main/java/com/arextest/schedule/serialization/ZstdJacksonSerializer.java
index ba362219..026eff42 100644
--- a/arex-schedule-web-api/src/main/java/com/arextest/schedule/serialization/ZstdJacksonSerializer.java
+++ b/arex-schedule-web-api/src/main/java/com/arextest/schedule/serialization/ZstdJacksonSerializer.java
@@ -5,6 +5,8 @@
import com.arextest.common.serialization.SerializationProviders;
import com.arextest.common.utils.SerializationUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Base64;
@@ -25,12 +27,26 @@ public final class ZstdJacksonSerializer {
@Resource
private ObjectMapper objectMapper;
private SerializationProvider serializationProvider;
+ public static final byte[] EMPTY_BYTE = new byte[]{};
@PostConstruct
void initSerializationProvider() {
this.serializationProvider = SerializationProviders.jacksonProvider(this.objectMapper);
}
+ public byte[] serialize(T value) {
+ if (value == null) {
+ return EMPTY_BYTE;
+ }
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ serializeTo(value, out);
+ return out.toByteArray();
+ } catch (IOException e) {
+ LOGGER.error("serialize error:{}", e.getMessage(), e);
+ }
+ return EMPTY_BYTE;
+ }
+
public void serializeTo(T value, OutputStream outputStream) {
if (value == null) {
return;
diff --git a/pom.xml b/pom.xml
index f3ad02a7..af24aa84 100644
--- a/pom.xml
+++ b/pom.xml
@@ -307,7 +307,7 @@
**/model/**,
**/mapping/**
- 1.2.19
+ 1.3.0
0.6.5.2
0.2.3
3.20.1
@@ -320,5 +320,5 @@
https://github.com/arextest/arex-replay-schedule
https://github.com/arextest/arex-replay-schedule
- 1.2.17
+ 1.2.18
\ No newline at end of file