Skip to content

Commit

Permalink
feat: change expectation script model name
Browse files Browse the repository at this point in the history
  • Loading branch information
mr3 committed Dec 16, 2023
1 parent 937984d commit f9a7be1
Show file tree
Hide file tree
Showing 14 changed files with 362 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,54 @@
import com.arextest.common.model.response.Response;
import com.arextest.common.model.response.ResponseCode;
import com.arextest.common.utils.ResponseUtils;
import com.arextest.web.core.repository.expectation.ExpectationScriptRepository;
import com.arextest.web.core.business.config.expectation.ExpectationScriptService;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptDeleteRequest;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptModel;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptQueryRequest;
import java.util.List;
import javax.validation.Valid;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/config/expectation")
public class ExpectationScriptController {
private final ExpectationScriptRepository repository;
private final ExpectationScriptService service;

public ExpectationScriptController(ExpectationScriptRepository repository) {
this.repository = repository;
public ExpectationScriptController(ExpectationScriptService service) {
this.service = service;
}

@RequestMapping("/query")
@RequestMapping(path = "/query", method = RequestMethod.POST)
@ResponseBody
public Response query(@Valid @RequestBody ExpectationScriptQueryRequest request) {
List<ExpectationScriptModel> list = repository.query(request);
return ResponseUtils.successResponse(list);
return ResponseUtils.successResponse(service.query(request));
}

@RequestMapping("/save")
@RequestMapping(path = "/save", method = RequestMethod.POST)
@ResponseBody
public Response save(@Valid @RequestBody ExpectationScriptModel request) {
boolean result = repository.save(request);
if (!result) {
return ResponseUtils.errorResponse("save failed", ResponseCode.REQUESTED_HANDLE_EXCEPTION);
boolean result = service.save(request);
if (result) {
return ResponseUtils.successResponse(true);
}
return ResponseUtils.successResponse(true);
if (CollectionUtils.isNotEmpty(request.getInvalidExtractAssertList())) {
String originalText = request.getInvalidExtractAssertList().get(0).getOriginalText();
return ResponseUtils.parameterInvalidResponse("invalid assert: " + originalText);
}
return ResponseUtils.errorResponse("save failed", ResponseCode.REQUESTED_HANDLE_EXCEPTION);
}

@RequestMapping("/delete")
@RequestMapping(path = "/delete", method = RequestMethod.POST)
@ResponseBody
public Response delete(@Valid @RequestBody ExpectationScriptDeleteRequest request) {
boolean result = repository.delete(request);
if (!result) {
return ResponseUtils.errorResponse("delete failed", ResponseCode.REQUESTED_HANDLE_EXCEPTION);
boolean result = service.delete(request);
if (result) {
return ResponseUtils.successResponse(true);
}
return ResponseUtils.successResponse(true);
return ResponseUtils.errorResponse("delete failed", ResponseCode.REQUESTED_HANDLE_EXCEPTION);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.arextest.web.core.business.config.expectation;

import com.arextest.web.core.repository.expectation.ExpectationScriptRepository;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptDeleteRequest;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptModel;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptQueryRequest;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

/**
* @since 2023/12/15
*/
@Service
public class ExpectationScriptService {
private final ExpectationScriptRepository repository;
private final ScriptNormalizer normalizer;

public ExpectationScriptService(ExpectationScriptRepository repository, ScriptNormalizer normalizer) {
this.repository = repository;
this.normalizer = normalizer;
}

public List<ExpectationScriptModel> query(ExpectationScriptQueryRequest request) {
return repository.query(request);
}

public boolean save(ExpectationScriptModel model) {
normalizer.normalize(model);
if (CollectionUtils.isNotEmpty(model.getInvalidExtractAssertList())) {
return false;
}
return model.getId() != null ? repository.update(model) : repository.insert(model);
}

public boolean delete(ExpectationScriptDeleteRequest request) {
return repository.delete(request.getId(), request.getAppId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.arextest.web.core.business.config.expectation;

import com.arextest.web.model.contract.contracts.config.expectation.ScriptExtractAssertModel;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptModel;

/**
* @since 2023/11/29
*/
public interface ScriptAssertHandler {
boolean support(ScriptExtractAssertModel model);
void handle(ExpectationScriptModel scriptModel, ScriptExtractAssertModel assertModel);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.arextest.web.core.business.config.expectation;

import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptModel;
import com.arextest.web.model.contract.contracts.config.expectation.ScriptExtractAssertModel;
import com.arextest.web.model.contract.contracts.config.expectation.ScriptExtractOperationModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

/**
* @since 2023/11/29
*/
@Component
public class ScriptNormalizer {
// (?:let (?<variable>\w+) = )?arex\.(?<category>[a-zA-Z]+){1}\[\"(?<operation>.+)\"]
private static final String EXTRACT_OPERATION_REGEX = "(?:var (?<variable>\\w+) = )?arex\\.(?<category>[a-zA-Z]+){1}\\[\"(?<operation>.+)\"]";
private static final Pattern EXTRACT_OPERATION_PATTERN = Pattern.compile(EXTRACT_OPERATION_REGEX);
// arex\.assert\.[a-zA-Z]+\(.*\);
private static final String EXTRACT_ASSERT_REGEX = "arex\\.assert\\.[a-zA-Z]+\\(.*\\);";
private static final Pattern EXTRACT_ASSERT_PATTERN = Pattern.compile(EXTRACT_ASSERT_REGEX);

private final List<ScriptAssertHandler> assertHandlerList;

public ScriptNormalizer(List<ScriptAssertHandler> assertHandlerList) {
this.assertHandlerList = assertHandlerList;
}

public void normalize(ExpectationScriptModel model) {
model.setNormalizedContent(model.getContent());
List<ScriptExtractOperationModel> extactOpeartionList = extactOpeartionList(model.getNormalizedContent());

if (extactOpeartionList.isEmpty()) {
return;
}

model.setExtractOperationList(extactOpeartionList);

// match script with EXTRACT_ASSERT_PATTERN
Matcher assertMatcher = EXTRACT_ASSERT_PATTERN.matcher(model.getNormalizedContent());
while (assertMatcher.find()) {
ScriptExtractAssertModel assertModel = new ScriptExtractAssertModel(assertMatcher.group());
for (ScriptAssertHandler handler : assertHandlerList) {
if (!handler.support(assertModel)) {
continue;
}
handler.handle(model, assertModel);
if (!assertModel.validate()) {
continue;
}
model.setNormalizedContent(StringUtils.replace(model.getNormalizedContent(), assertModel.getOriginalText(),
assertModel.rebuild()));
}
if (!assertModel.validate()) {
model.setInvalidExtractAssertList(Collections.singletonList(assertModel));
break;
}
}
}

private List<ScriptExtractOperationModel> extactOpeartionList(String script) {
List<ScriptExtractOperationModel> operationList = new ArrayList<>();
Matcher matcher = EXTRACT_OPERATION_PATTERN.matcher(script);
while (matcher.find()) {
ScriptExtractOperationModel operationModel = new ScriptExtractOperationModel();
operationModel.setVariableName(matcher.group("variable"));
operationModel.setCategoryName(matcher.group("category"));
operationModel.setOperationName(matcher.group("operation"));
operationModel.setOriginalText(matcher.group());
if (operationModel.validate() && !operationList.contains(operationModel)) {
operationList.add(operationModel);
}
}
return operationList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.arextest.web.core.business.config.expectation.assertion;

import com.arextest.web.core.business.config.expectation.ScriptAssertHandler;
import com.arextest.web.model.contract.contracts.config.expectation.ScriptExtractAssertModel;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptModel;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

/**
* @since 2023/11/29
*/
@Component
public class EqualsHandler implements ScriptAssertHandler {
// arex\.assert\.equals\((?<expected>\"\w+\"), *(?<service>\w+)\.request.(?<path>.*)\);
private static final String EQUALS_REGEX = "arex\\.assert\\.equals\\((?<expected>\"\\w+\"), *(?<service>.+)\\.(?:request|response)\\.(?<path>.*)\\);";
private static final Pattern EQUALS_PATTERN = Pattern.compile(EQUALS_REGEX);

// arex\.(?<category>[a-zA-Z]+){1}\[\"(?<operation>.+)\"]
private static final String OPERATION_REGEX = "arex\\.(?<category>[a-zA-Z]+){1}\\[\"(?<operation>.+)\"]";
private static final Pattern OPERATION_PATTERN = Pattern.compile(OPERATION_REGEX);

@Override
public boolean support(ScriptExtractAssertModel model) {
return model.getOriginalText().startsWith("arex.assert.equals");
}

@Override
public void handle(ExpectationScriptModel scriptModel, ScriptExtractAssertModel assertModel) {
Matcher equalsMatcher = EQUALS_PATTERN.matcher(assertModel.getOriginalText());
if (!equalsMatcher.find()) {
return;
}
assertModel.setMethodName("equals");
assertModel.setExpected(equalsMatcher.group("expected"));
assertModel.setShortServiceName(equalsMatcher.group("service"));
assertModel.setPath(equalsMatcher.group("path"));

if (StringUtils.startsWith(assertModel.getShortServiceName(), "arex")) {
Matcher operationMatcher = OPERATION_PATTERN.matcher(assertModel.getShortServiceName());
if (operationMatcher.find()) {
assertModel.setCategoryName(operationMatcher.group("category"));
assertModel.setOperationName(operationMatcher.group("operation"));
}
}

if (StringUtils.isNotEmpty(assertModel.getOperationName())) {
return;
}

scriptModel.getExtractOperationList().stream()
.filter(importsModel -> StringUtils.equals(importsModel.getVariableName(), assertModel.getShortServiceName()))
.findFirst()
.ifPresent(operation -> {
assertModel.setOperationName(operation.getOperationName());
assertModel.setCategoryName(operation.getCategoryName());
});
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.arextest.web.core.repository.expectation;

import com.arextest.web.core.repository.RepositoryProvider;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptDeleteRequest;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptModel;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptQueryRequest;
import com.arextest.web.model.dao.mongodb.expectation.ExpectationScriptCollection;
Expand All @@ -25,11 +24,11 @@ public class ExpectationScriptRepository implements RepositoryProvider {

public boolean insert(ExpectationScriptModel model) {
ExpectationScriptCollection entity = ExpectationScriptMapper.INSTANCE.toCollection(model);
if (entity.getExpirationTime() < 1L) {
if (entity.getExpirationTime() == null) {
// 2099-01-01 12:00:00
entity.setExpirationTime(4070923200000L);
}
entity.setValid(BooleanUtils.toBooleanDefaultIfNull(model.valid, true));
entity.setValid(BooleanUtils.toBooleanDefaultIfNull(model.getValid(), true));
entity.setDataChangeCreateTime(System.currentTimeMillis());
entity.setDataChangeUpdateTime(entity.getDataChangeCreateTime());
mongoTemplate.insert(entity);
Expand All @@ -43,23 +42,23 @@ public boolean update(ExpectationScriptModel model) {

Update update = getConfigUpdate();
update.set(Fields.content, model.getContent());
update.set(Fields.valid, BooleanUtils.toBooleanDefaultIfNull(model.valid, true));
update.set(Fields.expirationTime, model.getExpirationTime());
update.set(Fields.normalizedContent, model.getNormalizedContent());
update.set(Fields.extractOperationList, model.getExtractOperationList());
update.set(Fields.valid, BooleanUtils.toBooleanDefaultIfNull(model.getValid(), true));
if (model.getExpirationTime() != null) {
update.set(Fields.expirationTime, model.getExpirationTime());
}
update.set(Fields.scope, model.getScope());
update.set(Fields.dataChangeUpdateBy, model.getDataChangeUpdateBy());

UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ExpectationScriptCollection.class);
return updateResult.getModifiedCount() > 0;
}

public boolean save(ExpectationScriptModel model) {
return model.getId() != null ? update(model) : insert(model);
}

public boolean delete(ExpectationScriptDeleteRequest request) {
public boolean delete(String id, String appId) {
Query query = new Query();
query.addCriteria(Criteria.where(DASH_ID).is(request.getId()));
query.addCriteria(Criteria.where(Fields.appId).is(request.getAppId()));
query.addCriteria(Criteria.where(DASH_ID).is(id));
query.addCriteria(Criteria.where(Fields.appId).is(appId));
return mongoTemplate.remove(query, ExpectationScriptCollection.class).getDeletedCount() > 0;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.arextest.web.core.business.config.expectation;

import com.arextest.web.core.business.config.expectation.assertion.EqualsHandler;
import com.arextest.web.model.contract.contracts.config.expectation.ExpectationScriptModel;
import com.arextest.web.model.contract.contracts.config.expectation.ScriptExtractOperationModel;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

/**
* @since 2023/12/15
*/
class ScriptNormalizerTest {
static ScriptNormalizer scriptNormalizer;
static List<ScriptAssertHandler> scriptAssertHandlerList;

@BeforeEach
void setUp() {
scriptAssertHandlerList = new ArrayList<>(1);
scriptAssertHandlerList.add(new EqualsHandler());
scriptNormalizer = new ScriptNormalizer(scriptAssertHandlerList);
}

@AfterEach
void tearDown() {
}

@Test
void normalize() {
String script = " var serviceConsumerA = arex.SoaConsumer[\"HelloService.ConsumerA\"];\n"
+ " arex.assert.equals(\"serviceConsumerB\", serviceConsumerA.request.name);\n"
+ "\n"
+ " var serviceConsumerB = arex.SoaConsumer[\"HelloService.ConsumerB\"];\n"
+ " arex.assert.equals(\"serviceConsumerB\", serviceConsumerB.request.name);\n"
+ " \n"
+ " arex.assert.equals(\"mark4\", arex.SoaProvider[\"HelloService\"].response.order.id);";
ExpectationScriptModel expectationScript = new ExpectationScriptModel();
expectationScript.setAppId("test-service");
expectationScript.setOperationId("test-operation-id");
expectationScript.setContent(script);
expectationScript.setNormalizedContent(expectationScript.getContent());
scriptNormalizer.normalize(expectationScript);

assert expectationScript.getExtractOperationList().size() == 3;

for (ScriptExtractOperationModel operation : expectationScript.getExtractOperationList()) {
System.out.println(operation);
}
}
}
Loading

0 comments on commit f9a7be1

Please sign in to comment.