Skip to content

Commit

Permalink
feat: Compatible with replayResult interface logic
Browse files Browse the repository at this point in the history
  • Loading branch information
pangdayuan1 committed Sep 2, 2024
1 parent 8fb923d commit a96aa85
Show file tree
Hide file tree
Showing 15 changed files with 475 additions and 105 deletions.
4 changes: 2 additions & 2 deletions arex-schedule-web-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<parent>
<artifactId>arex-schedule-parent</artifactId>
<groupId>com.arextest</groupId>
<version>1.2.17</version>
<version>1.2.18</version>
</parent>

<profiles>
Expand Down Expand Up @@ -338,5 +338,5 @@
</properties>
</profile>
</profiles>
<version>1.2.17</version>
<version>1.2.18</version>
</project>
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -74,6 +75,7 @@ public final class HttpWepServiceApiClient {

@Autowired(required = false)
private List<ClientHttpRequestInterceptor> clientHttpRequestInterceptors;
private static final String ZSTD_JSON_CONTENT_TYPE = "application/zstd-json;charset=UTF-8";

@PostConstruct
private void initTemplate() {
Expand Down Expand Up @@ -250,6 +252,21 @@ public <TRequest, TResponse> ResponseEntity<TResponse> retryJsonPost(String url,
}
}

public <TRequest, TResponse> TResponse retryZstdJsonPost(String url, TRequest request,
Class<TResponse> responseType) {
Map<String, String> 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 <TRequest> HttpEntity<TRequest> wrapJsonContentType(TRequest request) {
HttpEntity<TRequest> httpJsonEntity;
Expand All @@ -271,7 +288,9 @@ private <TRequest> HttpEntity<TRequest> wrapJsonContentType(TRequest request,
httpJsonEntity = (HttpEntity<TRequest>) 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public ZstdJacksonMessageConverter() {

@Override
protected boolean supports(Class<?> clazz) {
return true;
return !(clazz == byte[].class || clazz.isPrimitive());
}

@Override
Expand All @@ -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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,29 @@
public class JsonUtils {
private static final ObjectMapper objectMapper = new ObjectMapper();

public static <T> T byteToObject(byte[] bytes, Class<T> tClass) {
public static <T> T byteToObject(byte[] bytes, Class<T> tClazz) {
try {
return objectMapper.readValue(bytes, tClass);
return objectMapper.readValue(bytes, tClazz);
} catch (IOException e) {
LOGGER.error("byteToObject error:{}", e.getMessage(), e);
}
return null;
}

public static <T> T jsonStringToObject(String string, Class<T> tClazz) {
try {
return objectMapper.readValue(string, tClazz);
} 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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.arextest.schedule.comparer;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;

/**
Expand All @@ -11,6 +12,22 @@
public class CategoryComparisonHolder {

private String categoryName;
/**
* Need to match the comparison relationship
*/
private List<CompareItem> record;
private List<CompareItem> replayResult;

private Boolean needMatch;
/**
* Not need to match the comparison relationship
*/
private CompareResultItem compareResultItem;

@Data
@AllArgsConstructor
public static class CompareResultItem {
CompareItem recordItem;
CompareItem replayItem;
}
}
Original file line number Diff line number Diff line change
@@ -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<String, CompareItemConverter> categoryConverters;
@Resource
private CompareItemConverter defaultCompareItemConverterImpl;

public CompareItemConvertFactory(@Autowired List<CompareItemConverter> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
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) {
if (mocker == null || mocker.getCategoryType() == null) {
return null;
}

String operationKey = getOperationName(mocker.getTargetRequest(), mocker.getOperationName());
return new CompareItemImpl(operationKey, buildAttributes(mocker.getTargetRequest()).toString(),
mocker.getId(), mocker.getCreationTime(), mocker.getCategoryType().isEntryPoint());
}

@Override
public CompareItem convert(CompareRelationResult relationResult, boolean recordCompareItem) {
if (relationResult == null || relationResult.getCategoryType() == null) {
return null;
}

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<String, Object> attributes = target.getAttributes();
if (attributes != null) {
for (Entry<String, Object> 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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) {
if (mocker == null || mocker.getCategoryType() == null) {
return null;
}

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) {
if (relationResult == null) {
return null;
}

return new CompareItemImpl(relationResult, recordCompareItem);
}

}
Loading

0 comments on commit a96aa85

Please sign in to comment.