feat(TCPMock服务): 参考HTTP MOCK功能新增TCP MOCK功能#1001753
https://www.tapd.cn/55049933/prong/stories/view/1155049933001001753#
This commit is contained in:
parent
54ba05d9f4
commit
a326c7fd77
|
@ -292,12 +292,7 @@ public class ApiDefinitionController {
|
|||
|
||||
@GetMapping("/getMockEnvironment/{projectId}/{protocal}")
|
||||
public ApiTestEnvironmentWithBLOBs getMockEnvironment(@PathVariable String projectId, @PathVariable String protocal, HttpServletRequest request) {
|
||||
String requestUrl = request.getRequestURL().toString();
|
||||
String baseUrl = "";
|
||||
if (requestUrl.contains("/api/definition")) {
|
||||
baseUrl = requestUrl.split("/api/definition")[0];
|
||||
}
|
||||
return apiTestEnvironmentService.getMockEnvironmentByProjectId(projectId, protocal, baseUrl);
|
||||
return apiTestEnvironmentService.getMockEnvironmentByProjectId(projectId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -86,4 +86,8 @@ public class ApiTestEnvironmentController {
|
|||
apiTestEnvironmentService.delete(id);
|
||||
}
|
||||
|
||||
@GetMapping("/getTcpMockInfo/{projectId}")
|
||||
public String getMockInfo(@PathVariable(value = "projectId") String projectId) {
|
||||
return apiTestEnvironmentService.getMockInfo(projectId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.dto.automation;
|
|||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
|
@ -177,4 +178,22 @@ public class EsbDataStruct {
|
|||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public List<String> getNameDeep() {
|
||||
List<String> returnList = new ArrayList<>();
|
||||
if(StringUtils.isNotEmpty(this.name)){
|
||||
returnList.add(this.name);
|
||||
}
|
||||
if(CollectionUtils.isNotEmpty(this.children)){
|
||||
for (EsbDataStruct child :this.children) {
|
||||
List<String> itemNameList = child.getNameDeep();
|
||||
for (String itemName :itemNameList) {
|
||||
if(!returnList.contains(itemName)){
|
||||
returnList.add(itemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.dto.automation;
|
|||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
|
@ -11,7 +12,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* //ESB数据格式
|
||||
* 树形表格数据格式
|
||||
*
|
||||
* @author song.tianyang
|
||||
* @Date 2021/3/15 4:37 下午
|
||||
|
@ -181,4 +182,22 @@ public class TcpTreeTableDataStruct {
|
|||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public List<String> getNameDeep() {
|
||||
List<String> returnList = new ArrayList<>();
|
||||
if(StringUtils.isNotEmpty(this.name)){
|
||||
returnList.add(this.name);
|
||||
}
|
||||
if(CollectionUtils.isNotEmpty(this.children)){
|
||||
for (TcpTreeTableDataStruct child :this.children) {
|
||||
List<String> itemNameList = child.getNameDeep();
|
||||
for (String itemName :itemNameList) {
|
||||
if(!returnList.contains(itemName)){
|
||||
returnList.add(itemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
|
|||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestEnvironmentDTO;
|
||||
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
|
||||
import io.metersphere.api.tcp.TCPPool;
|
||||
import io.metersphere.base.domain.ApiTestEnvironmentExample;
|
||||
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
||||
import io.metersphere.base.domain.Project;
|
||||
|
@ -138,10 +139,12 @@ public class ApiTestEnvironmentService {
|
|||
* @param projectId
|
||||
* @return
|
||||
*/
|
||||
public synchronized ApiTestEnvironmentWithBLOBs getMockEnvironmentByProjectId(String projectId, String protocal, String baseUrl) {
|
||||
//创建的时候检查当前站点
|
||||
public synchronized ApiTestEnvironmentWithBLOBs getMockEnvironmentByProjectId(String projectId) {
|
||||
|
||||
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
|
||||
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
|
||||
String baseUrl = baseSystemConfigDTO.getUrl();
|
||||
String protocal = "http";
|
||||
if (baseSystemConfigDTO != null && StringUtils.isNotEmpty(baseSystemConfigDTO.getUrl())) {
|
||||
baseUrl = baseSystemConfigDTO.getUrl();
|
||||
if (baseUrl.startsWith("http:")) {
|
||||
|
@ -170,6 +173,8 @@ public class ApiTestEnvironmentService {
|
|||
|
||||
private ApiTestEnvironmentWithBLOBs checkMockEvnIsRightful(ApiTestEnvironmentWithBLOBs returnModel, String protocal, String projectId,String projectNumber, String name, String url) {
|
||||
boolean needUpdate = false;
|
||||
ProjectService projectService = CommonBeanFactory.getBean(ProjectService.class);
|
||||
Project project = projectService.getProjectById(projectId);
|
||||
if (returnModel.getConfig() != null) {
|
||||
try {
|
||||
JSONObject configObj = JSONObject.parseObject(returnModel.getConfig());
|
||||
|
@ -207,6 +212,26 @@ public class ApiTestEnvironmentService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(project.getMockTcpPort() != null && project.getMockTcpPort().intValue() != 0){
|
||||
if(configObj.containsKey("tcpConfig")){
|
||||
if(configObj.containsKey("port")){
|
||||
if(configObj.getInteger("port").intValue() != project.getMockTcpPort().intValue()){
|
||||
needUpdate = true;
|
||||
}
|
||||
}else {
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if(configObj.containsKey("server")){
|
||||
if(!StringUtils.equals(configObj.getString("server"),url)){
|
||||
needUpdate = true;
|
||||
}
|
||||
}else {
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
needUpdate = true;
|
||||
e.printStackTrace();
|
||||
|
@ -214,21 +239,35 @@ public class ApiTestEnvironmentService {
|
|||
}
|
||||
if (needUpdate) {
|
||||
String id = returnModel.getId();
|
||||
returnModel = this.genHttpApiTestEnvironmentByUrl(projectId,projectNumber, protocal, name, url);
|
||||
returnModel = this.genHttpApiTestEnvironmentByUrl(project,projectNumber, protocal, name, url);
|
||||
returnModel.setId(id);
|
||||
apiTestEnvironmentMapper.updateByPrimaryKeyWithBLOBs(returnModel);
|
||||
}
|
||||
return returnModel;
|
||||
}
|
||||
|
||||
private ApiTestEnvironmentWithBLOBs genHttpApiTestEnvironmentByUrl(String projectId,String projectNumber, String protocal, String name, String url) {
|
||||
private ApiTestEnvironmentWithBLOBs genHttpApiTestEnvironmentByUrl(String projectId,String projectNumber, String protocal, String name, String baseUrl) {
|
||||
ProjectService projectService = CommonBeanFactory.getBean(ProjectService.class);
|
||||
Project project = projectService.getProjectById(projectId);
|
||||
if(project != null){
|
||||
return this.genHttpApiTestEnvironmentByUrl(project,projectNumber, protocal, name, baseUrl);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ApiTestEnvironmentWithBLOBs genHttpApiTestEnvironmentByUrl(Project project,String projectNumber, String protocal, String name, String baseUrl) {
|
||||
String socket = "";
|
||||
String url = baseUrl;
|
||||
if (url.startsWith("http://")) {
|
||||
url = url.substring(7);
|
||||
} else if (url.startsWith("https://")) {
|
||||
url = url.substring(8);
|
||||
}
|
||||
socket = url;
|
||||
String tcpSocket = socket;
|
||||
if(StringUtils.isNotEmpty(tcpSocket) && tcpSocket.contains(":")){
|
||||
tcpSocket = socket.split(":")[0];
|
||||
}
|
||||
|
||||
String portStr = "";
|
||||
String ipStr = url;
|
||||
|
@ -301,6 +340,10 @@ public class ApiTestEnvironmentService {
|
|||
tcpConfigObj.put("reUseConnection", false);
|
||||
tcpConfigObj.put("nodelay", false);
|
||||
tcpConfigObj.put("closeConnection", false);
|
||||
if(project.getMockTcpPort() != null && project.getMockTcpPort().intValue() != 0){
|
||||
tcpConfigObj.put("server", tcpSocket);
|
||||
tcpConfigObj.put("port", 12138);
|
||||
}
|
||||
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("commonConfig", commonConfigObj);
|
||||
|
@ -309,7 +352,7 @@ public class ApiTestEnvironmentService {
|
|||
object.put("tcpConfig", tcpConfigObj);
|
||||
|
||||
ApiTestEnvironmentWithBLOBs blobs = new ApiTestEnvironmentWithBLOBs();
|
||||
blobs.setProjectId(projectId);
|
||||
blobs.setProjectId(project.getId());
|
||||
blobs.setName(name);
|
||||
blobs.setConfig(object.toString());
|
||||
|
||||
|
@ -353,4 +396,36 @@ public class ApiTestEnvironmentService {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getMockInfo(String projectId) {
|
||||
String returnStr = "";
|
||||
ApiTestEnvironmentWithBLOBs mockEnv = this.getMockEnvironmentByProjectId(projectId);
|
||||
if (mockEnv != null && mockEnv.getConfig() != null) {
|
||||
try {
|
||||
JSONObject configObj = JSONObject.parseObject(mockEnv.getConfig());
|
||||
|
||||
if(configObj.containsKey("tcpConfig")){
|
||||
JSONObject tcpConfigObj = configObj.getJSONObject("tcpConfig");
|
||||
int tcpPort = 0;
|
||||
if(tcpConfigObj.containsKey("port")){
|
||||
tcpPort = tcpConfigObj.getInteger("port").intValue();
|
||||
if(tcpPort == 0 || !TCPPool.isTcpOpen(tcpPort)){
|
||||
return returnStr;
|
||||
}
|
||||
}else {
|
||||
return returnStr;
|
||||
}
|
||||
if(tcpConfigObj.containsKey("server")){
|
||||
String server = tcpConfigObj.getString("server");
|
||||
returnStr = server +":"+ tcpPort;
|
||||
}else {
|
||||
return returnStr;
|
||||
}
|
||||
}
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return returnStr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import com.alibaba.fastjson.JSON;
|
|||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONValidator;
|
||||
import io.metersphere.api.dto.automation.EsbDataStruct;
|
||||
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
||||
import io.metersphere.api.dto.automation.parse.TcpTreeTableDataParser;
|
||||
import io.metersphere.api.dto.mockconfig.MockConfigRequest;
|
||||
import io.metersphere.api.dto.mockconfig.MockExpectConfigRequest;
|
||||
import io.metersphere.api.dto.mockconfig.response.JsonSchemaReturnObj;
|
||||
|
@ -12,22 +15,28 @@ import io.metersphere.api.dto.mockconfig.response.MockExpectConfigResponse;
|
|||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.MockConfigMapper;
|
||||
import io.metersphere.base.mapper.MockExpectConfigMapper;
|
||||
import io.metersphere.base.mapper.ProjectMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtMockExpectConfigMapper;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.JsonPathUtils;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.jmeter.utils.ScriptEngineUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.XML;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -39,7 +48,11 @@ public class MockConfigService {
|
|||
@Resource
|
||||
private MockExpectConfigMapper mockExpectConfigMapper;
|
||||
@Resource
|
||||
private ExtMockExpectConfigMapper extMockExpectConfigMapper;
|
||||
@Resource
|
||||
private ApiDefinitionService apiDefinitionService;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
|
||||
public MockConfigResponse findByApiIdList(List<String> apiIdList) {
|
||||
if (apiIdList.isEmpty()) {
|
||||
|
@ -247,7 +260,7 @@ public class MockConfigService {
|
|||
}
|
||||
}
|
||||
|
||||
boolean mathing = JsonPathUtils.checkJsonObjCompliance(reqJsonObj, mockExpectJson);
|
||||
boolean mathing = JsonStructUtils.checkJsonObjCompliance(reqJsonObj, mockExpectJson);
|
||||
if (mathing) {
|
||||
returnModel = model;
|
||||
break;
|
||||
|
@ -312,14 +325,14 @@ public class MockConfigService {
|
|||
JSONArray mockExpectArr = JSONArray.parseArray(jsonParams);
|
||||
for (int expectIndex = 0; expectIndex < mockExpectArr.size(); expectIndex++) {
|
||||
JSONObject itemObj = mockExpectArr.getJSONObject(expectIndex);
|
||||
mathing = JsonPathUtils.checkJsonArrayCompliance(reqJsonArray, itemObj);
|
||||
mathing = JsonStructUtils.checkJsonArrayCompliance(reqJsonArray, itemObj);
|
||||
if (!mathing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (StringUtils.equalsIgnoreCase("Object", jsonValidator.getType().name())) {
|
||||
JSONObject mockExpectJson = JSONObject.parseObject(jsonParams);
|
||||
mathing = JsonPathUtils.checkJsonArrayCompliance(reqJsonArray, mockExpectJson);
|
||||
mathing = JsonStructUtils.checkJsonArrayCompliance(reqJsonArray, mockExpectJson);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -339,7 +352,7 @@ public class MockConfigService {
|
|||
mockExpectJson.put(name, value);
|
||||
}
|
||||
}
|
||||
mathing = JsonPathUtils.checkJsonArrayCompliance(reqJsonArray, mockExpectJson);
|
||||
mathing = JsonStructUtils.checkJsonArrayCompliance(reqJsonArray, mockExpectJson);
|
||||
}
|
||||
if (mathing) {
|
||||
returnModel = model;
|
||||
|
@ -732,39 +745,51 @@ public class MockConfigService {
|
|||
}
|
||||
}
|
||||
|
||||
// List<String> sendParams = new ArrayList<>();
|
||||
// for (String param : pathArr) {
|
||||
// if (param.startsWith("{") && param.endsWith("}")) {
|
||||
// param = param.substring(1, param.length() - 1);
|
||||
// sendParams.add(param);
|
||||
// }
|
||||
// }
|
||||
// try {
|
||||
// JSONObject requestJson = JSONObject.parseObject(api.getRequest());
|
||||
// if (requestJson.containsKey("rest")) {
|
||||
// JSONArray jsonArray = requestJson.getJSONArray("rest");
|
||||
// for (int i = 0; i < jsonArray.size(); i++) {
|
||||
// JSONObject object = jsonArray.getJSONObject(i);
|
||||
// if (object.containsKey("name") && object.containsKey("enable") && object.getBoolean("enable")) {
|
||||
// String name = object.getString("name");
|
||||
// if (sendParams.contains(name)) {
|
||||
// String value = "";
|
||||
// if (object.containsKey("value")) {
|
||||
// value = object.getString("value");
|
||||
// }
|
||||
// returnJson.put(name, value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
return returnJson;
|
||||
}
|
||||
|
||||
public List<Map<String, String>> getApiParamsByApiDefinitionBLOBs(ApiDefinitionWithBLOBs apiModel) {
|
||||
if (apiModel == null) {
|
||||
return new ArrayList<>();
|
||||
} else if (StringUtils.equalsIgnoreCase("tcp", apiModel.getMethod())) {
|
||||
return this.getTCPApiParams(apiModel);
|
||||
} else {
|
||||
return this.getHTTPApiParams(apiModel);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Map<String, String>> getTCPApiParams(ApiDefinitionWithBLOBs apiModel) {
|
||||
List<Map<String, String>> list = new ArrayList<>();
|
||||
List<String> paramNameList = new ArrayList<>();
|
||||
if (apiModel != null) {
|
||||
if (apiModel.getRequest() != null) {
|
||||
JSONObject requestObj = this.genJSONObject(apiModel.getRequest());
|
||||
if (requestObj != null && requestObj.containsKey("reportType")) {
|
||||
String reportType = requestObj.getString("reportType");
|
||||
if (StringUtils.equalsIgnoreCase(reportType, "xml") && requestObj.containsKey("xmlDataStruct")) {
|
||||
paramNameList = this.parseByTcpTreeDataStruct(requestObj.getString("xmlDataStruct"));
|
||||
} else if (StringUtils.equalsIgnoreCase(reportType, "json") && requestObj.containsKey("jsonDataStruct")) {
|
||||
paramNameList = this.parseByJsonDataStruct(requestObj.getString("jsonDataStruct"));
|
||||
} else if (requestObj.containsKey("protocol")) {
|
||||
String protocol = requestObj.getString("protocol");
|
||||
if (StringUtils.equalsIgnoreCase("ESB", protocol) && requestObj.containsKey("esbDataStruct")) {
|
||||
paramNameList = this.parseByESBDataStruct(requestObj.getString("esbDataStruct"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String param : paramNameList) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("value", param);
|
||||
list.add(map);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Map<String, String>> getHTTPApiParams(ApiDefinitionWithBLOBs apiModel) {
|
||||
List<Map<String, String>> list = new ArrayList<>();
|
||||
List<String> paramNameList = new ArrayList<>();
|
||||
if (apiModel != null) {
|
||||
|
@ -1001,4 +1026,165 @@ public class MockConfigService {
|
|||
}
|
||||
return new String(buffer, charEncoding);
|
||||
}
|
||||
|
||||
private List<String> parseByJsonDataStruct(String dataString) {
|
||||
List<String> returnList = new ArrayList<>();
|
||||
try {
|
||||
JSONValidator validator = JSONValidator.from(dataString);
|
||||
Map<String, String> keyValueMap = new HashMap<>();
|
||||
if (StringUtils.equalsIgnoreCase(validator.getType().name(), "Object")) {
|
||||
JsonStructUtils.deepParseKeyByJsonObject(JSONObject.parseObject(dataString), returnList);
|
||||
} else if (StringUtils.equalsIgnoreCase(validator.getType().name(), "Array")) {
|
||||
JsonStructUtils.deepParseKeyByJsonArray(JSONArray.parseArray(dataString), returnList);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage());
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private List<String> parseByTcpTreeDataStruct(String dataString) {
|
||||
List<TcpTreeTableDataStruct> list = JSONArray.parseArray(dataString, TcpTreeTableDataStruct.class);
|
||||
List<String> returnList = new ArrayList<>();
|
||||
for (TcpTreeTableDataStruct dataStruct : list) {
|
||||
List<String> nameList = dataStruct.getNameDeep();
|
||||
for (String name : nameList) {
|
||||
if (!returnList.contains(nameList)) {
|
||||
returnList.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private List<String> parseByESBDataStruct(String dataString) {
|
||||
List<EsbDataStruct> list = JSONArray.parseArray(dataString, EsbDataStruct.class);
|
||||
List<String> returnList = new ArrayList<>();
|
||||
for (EsbDataStruct dataStruct : list) {
|
||||
List<String> nameList = dataStruct.getNameDeep();
|
||||
for (String name : nameList) {
|
||||
if (!returnList.contains(nameList)) {
|
||||
returnList.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public MockExpectConfigWithBLOBs matchTcpMockExpect(String message, int port) {
|
||||
ProjectExample projectExample = new ProjectExample();
|
||||
projectExample.createCriteria().andMockTcpPortEqualTo(port).andIsMockTcpOpenEqualTo(true);
|
||||
List<Project> projectList = projectMapper.selectByExample(projectExample);
|
||||
|
||||
boolean isJsonMessage = this.checkMessageIsJson(message);
|
||||
boolean isXMLMessage = this.checkMessageIsXml(message);
|
||||
|
||||
List<MockExpectConfigWithBLOBs> structResult = new ArrayList<>();
|
||||
List<MockExpectConfigWithBLOBs> rawResult = new ArrayList<>();
|
||||
|
||||
for (Project project : projectList) {
|
||||
String projectId = project.getId();
|
||||
List<MockExpectConfigWithBLOBs> mockExpectConfigList = extMockExpectConfigMapper.selectByProjectIdAndStatusIsOpen(projectId);
|
||||
for (MockExpectConfigWithBLOBs expectConfig : mockExpectConfigList) {
|
||||
String requestStr = expectConfig.getRequest();
|
||||
String responseStr = expectConfig.getResponse();
|
||||
if (StringUtils.isEmpty(responseStr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject requestJson = JSONObject.parseObject(requestStr);
|
||||
if (requestJson.containsKey("reportType")) {
|
||||
boolean isMatch = false;
|
||||
boolean isRaw = false;
|
||||
String reportType = requestJson.getString("reportType");
|
||||
|
||||
if (isJsonMessage && StringUtils.equalsIgnoreCase(reportType, "json")) {
|
||||
if (requestJson.containsKey("jsonDataStruct")) {
|
||||
isMatch = JsonStructUtils.checkJsonCompliance(message, requestJson.getString("jsonDataStruct"));
|
||||
}
|
||||
} else if (isXMLMessage && StringUtils.equalsIgnoreCase(reportType, "xml")) {
|
||||
if (requestJson.containsKey("xmlDataStruct")) {
|
||||
JSONObject sourceObj = XMLUtils.XmlToJson(message);
|
||||
String xmlStr = "";
|
||||
try {
|
||||
List<TcpTreeTableDataStruct> tcpDataList = JSONArray.parseArray(requestJson.getString("xmlDataStruct"),TcpTreeTableDataStruct.class);
|
||||
xmlStr = TcpTreeTableDataParser.treeTableData2Xml(tcpDataList);
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
JSONObject matchObj = XMLUtils.XmlToJson(xmlStr);
|
||||
isMatch = JsonStructUtils.checkJsonObjCompliance(sourceObj, matchObj);
|
||||
}
|
||||
} else if (StringUtils.equalsIgnoreCase(reportType, "raw")) {
|
||||
if (requestJson.containsKey("rawDataStruct")) {
|
||||
String rawDataStruct = requestJson.getString("rawDataStruct");
|
||||
if (StringUtils.contains(message, rawDataStruct)) {
|
||||
isMatch = true;
|
||||
isRaw = true;
|
||||
} else {
|
||||
Pattern pattern = Pattern.compile(rawDataStruct);
|
||||
Matcher matcher = pattern.matcher(message);
|
||||
if (matcher.find()) {
|
||||
isMatch = true;
|
||||
isRaw = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isMatch) {
|
||||
JSONObject responseObj = JSONObject.parseObject(responseStr);
|
||||
if (responseObj.containsKey("body")) {
|
||||
if (isRaw) {
|
||||
rawResult.add(expectConfig);
|
||||
} else {
|
||||
structResult.add(expectConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
//优先返回结构匹配的数据
|
||||
if(!structResult.isEmpty()){
|
||||
return structResult.get(0);
|
||||
}else {
|
||||
if(!rawResult.isEmpty()){
|
||||
return rawResult.get(0);
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkMessageIsXml(String message) {
|
||||
boolean isXml = false;
|
||||
try {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
|
||||
// builder.parse(message);
|
||||
builder.parse(new InputSource(new ByteArrayInputStream(message.getBytes("utf-8"))));
|
||||
isXml = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return isXml;
|
||||
}
|
||||
|
||||
private boolean checkMessageIsJson(String message) {
|
||||
boolean isJson = false;
|
||||
try {
|
||||
JSONValidator validator = JSONValidator.from(message);
|
||||
String type = validator.getType().name();
|
||||
if (!StringUtils.equalsIgnoreCase("value", type)) {
|
||||
isJson = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return isJson;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package io.metersphere.api.tcp;
|
||||
|
||||
import io.metersphere.api.tcp.server.TCPServer;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/8/10 3:04 下午
|
||||
*/
|
||||
public class TCPPool {
|
||||
|
||||
private static HashMap<Integer, TCPServer> serverSockedMap = new HashMap<>();
|
||||
|
||||
private TCPPool(){}
|
||||
|
||||
public static String createTcp(int port){
|
||||
String returnString = "";
|
||||
TCPServer tcpServer = null;
|
||||
if(serverSockedMap.containsKey(port)){
|
||||
tcpServer = serverSockedMap.get(port);
|
||||
}else {
|
||||
tcpServer = new TCPServer(port);
|
||||
serverSockedMap.put(port,tcpServer);
|
||||
}
|
||||
try {
|
||||
if(!tcpServer.isSocketOpen()){
|
||||
Thread t = new Thread(tcpServer);
|
||||
t.start();
|
||||
}
|
||||
returnString = "OK";
|
||||
}catch (Exception e){
|
||||
returnString = e.getMessage();
|
||||
e.printStackTrace();
|
||||
MSException.throwException(e.getMessage());
|
||||
}
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
public static boolean isTcpOpen(int port){
|
||||
TCPServer server = serverSockedMap.get(port);
|
||||
if(server != null ){
|
||||
return server.isSocketOpen();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getTcpStatus() {
|
||||
if(serverSockedMap.isEmpty()){
|
||||
return "null";
|
||||
}else {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
for (Map.Entry<Integer, TCPServer> entry:serverSockedMap.entrySet()) {
|
||||
int port = entry.getKey();
|
||||
TCPServer tcpServer = entry.getValue();
|
||||
if(tcpServer == null){
|
||||
stringBuffer.append("Port is "+port + ";");
|
||||
stringBuffer.append("Server is null;");
|
||||
}else {
|
||||
stringBuffer.append("Port is "+port + ";");
|
||||
stringBuffer.append("Server is open: "+ tcpServer.isSocketOpen());
|
||||
}
|
||||
}
|
||||
return stringBuffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String closeTcp(int portNum) {
|
||||
TCPServer server = serverSockedMap.get(portNum);
|
||||
if(server == null){
|
||||
return "Tcp Is not create!";
|
||||
}else {
|
||||
String returnMsg = null;
|
||||
try {
|
||||
server.closeSocket();
|
||||
returnMsg = "OK";
|
||||
}catch (Exception e){
|
||||
returnMsg = e.getMessage();
|
||||
e.printStackTrace();
|
||||
}
|
||||
return returnMsg;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package io.metersphere.api.tcp.server;
|
||||
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/8/11 10:35 上午
|
||||
*/
|
||||
public class TCPServer implements Runnable {
|
||||
private int port;
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
private TCPServicer servicer;
|
||||
|
||||
public TCPServer(int port){
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void openSocket() throws Exception {
|
||||
this.serverSocket = new ServerSocket(this.port);
|
||||
int connectIndex = 0;
|
||||
|
||||
while (true) {
|
||||
if (!this.serverSocket.isClosed()) {
|
||||
Socket socket = this.serverSocket.accept();
|
||||
servicer = new TCPServicer(socket,port);
|
||||
servicer.run();
|
||||
}
|
||||
if (this.serverSocket.isClosed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSocketOpen(){
|
||||
if (this.serverSocket != null && !this.serverSocket.isClosed()) {
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void closeSocket() throws Exception {
|
||||
if (this.serverSocket != null && !this.serverSocket.isClosed()) {
|
||||
if(servicer != null){
|
||||
servicer.close();
|
||||
}
|
||||
this.serverSocket.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
this.openSocket();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package io.metersphere.api.tcp.server;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.service.MockConfigService;
|
||||
import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
public class TCPServicer {
|
||||
private Socket s;
|
||||
private InputStream is;
|
||||
private OutputStream os;
|
||||
private int port;
|
||||
public TCPServicer(Socket s, int port) {
|
||||
this.s = s;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
byte[] b = new byte[1024];
|
||||
String returnMsg = "";
|
||||
String message = "";
|
||||
try {
|
||||
is = s.getInputStream();
|
||||
os = s.getOutputStream();
|
||||
int len = is.read(b);
|
||||
message = new String(b,0,len);
|
||||
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
returnMsg = this.getReturnMsg(message);
|
||||
|
||||
// try {
|
||||
os.write(returnMsg.getBytes());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
this.close();
|
||||
}
|
||||
|
||||
//关闭资源
|
||||
// this.close();
|
||||
}
|
||||
|
||||
private String getReturnMsg(String message) {
|
||||
MockConfigService mockConfigService = CommonBeanFactory.getBean(MockConfigService.class);
|
||||
MockExpectConfigWithBLOBs matchdMockExpect = mockConfigService.matchTcpMockExpect(message,this.port);
|
||||
String response = matchdMockExpect.getResponse();
|
||||
JSONObject responseObj = JSONObject.parseObject(response);
|
||||
try {
|
||||
int delayed = responseObj.getInteger("delayed");
|
||||
Thread.sleep(delayed);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String returnMsg = responseObj.getString("body");
|
||||
|
||||
return returnMsg;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
//关闭资源
|
||||
try{
|
||||
is.close();
|
||||
}catch (Exception e){}finally {
|
||||
try{
|
||||
os.close();
|
||||
}catch (Exception e){}finally {
|
||||
try{
|
||||
s.close();
|
||||
}catch (Exception e){}finally {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -39,5 +39,9 @@ public class Project implements Serializable {
|
|||
|
||||
private String systemId;
|
||||
|
||||
private Integer mockTcpPort;
|
||||
|
||||
private Boolean isMockTcpOpen;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -1243,6 +1243,126 @@ public class ProjectExample {
|
|||
addCriterion("system_id not between", value1, value2, "systemId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortIsNull() {
|
||||
addCriterion("mock_tcp_port is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortIsNotNull() {
|
||||
addCriterion("mock_tcp_port is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortEqualTo(Integer value) {
|
||||
addCriterion("mock_tcp_port =", value, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortNotEqualTo(Integer value) {
|
||||
addCriterion("mock_tcp_port <>", value, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortGreaterThan(Integer value) {
|
||||
addCriterion("mock_tcp_port >", value, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortGreaterThanOrEqualTo(Integer value) {
|
||||
addCriterion("mock_tcp_port >=", value, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortLessThan(Integer value) {
|
||||
addCriterion("mock_tcp_port <", value, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortLessThanOrEqualTo(Integer value) {
|
||||
addCriterion("mock_tcp_port <=", value, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortIn(List<Integer> values) {
|
||||
addCriterion("mock_tcp_port in", values, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortNotIn(List<Integer> values) {
|
||||
addCriterion("mock_tcp_port not in", values, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortBetween(Integer value1, Integer value2) {
|
||||
addCriterion("mock_tcp_port between", value1, value2, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andMockTcpPortNotBetween(Integer value1, Integer value2) {
|
||||
addCriterion("mock_tcp_port not between", value1, value2, "mockTcpPort");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenIsNull() {
|
||||
addCriterion("is_mock_tcp_open is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenIsNotNull() {
|
||||
addCriterion("is_mock_tcp_open is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenEqualTo(Boolean value) {
|
||||
addCriterion("is_mock_tcp_open =", value, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenNotEqualTo(Boolean value) {
|
||||
addCriterion("is_mock_tcp_open <>", value, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenGreaterThan(Boolean value) {
|
||||
addCriterion("is_mock_tcp_open >", value, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenGreaterThanOrEqualTo(Boolean value) {
|
||||
addCriterion("is_mock_tcp_open >=", value, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenLessThan(Boolean value) {
|
||||
addCriterion("is_mock_tcp_open <", value, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenLessThanOrEqualTo(Boolean value) {
|
||||
addCriterion("is_mock_tcp_open <=", value, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenIn(List<Boolean> values) {
|
||||
addCriterion("is_mock_tcp_open in", values, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenNotIn(List<Boolean> values) {
|
||||
addCriterion("is_mock_tcp_open not in", values, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("is_mock_tcp_open between", value1, value2, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIsMockTcpOpenNotBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("is_mock_tcp_open not between", value1, value2, "isMockTcpOpen");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
<result column="scenario_custom_num" jdbcType="BIT" property="scenarioCustomNum" />
|
||||
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
|
||||
<result column="system_id" jdbcType="VARCHAR" property="systemId" />
|
||||
<result column="mock_tcp_port" jdbcType="INTEGER" property="mockTcpPort" />
|
||||
<result column="is_mock_tcp_open" jdbcType="BIT" property="isMockTcpOpen" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -81,7 +83,7 @@
|
|||
<sql id="Base_Column_List">
|
||||
id, workspace_id, `name`, description, create_time, update_time, tapd_id, jira_key,
|
||||
zentao_id, azure_devops_id, `repeatable`, case_template_id, issue_template_id, custom_num,
|
||||
scenario_custom_num, create_user, system_id
|
||||
scenario_custom_num, create_user, system_id, mock_tcp_port, is_mock_tcp_open
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.ProjectExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -119,13 +121,15 @@
|
|||
tapd_id, jira_key, zentao_id,
|
||||
azure_devops_id, `repeatable`, case_template_id,
|
||||
issue_template_id, custom_num, scenario_custom_num,
|
||||
create_user, system_id)
|
||||
create_user, system_id, mock_tcp_port,
|
||||
is_mock_tcp_open)
|
||||
values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{tapdId,jdbcType=VARCHAR}, #{jiraKey,jdbcType=VARCHAR}, #{zentaoId,jdbcType=VARCHAR},
|
||||
#{azureDevopsId,jdbcType=VARCHAR}, #{repeatable,jdbcType=BIT}, #{caseTemplateId,jdbcType=VARCHAR},
|
||||
#{issueTemplateId,jdbcType=VARCHAR}, #{customNum,jdbcType=BIT}, #{scenarioCustomNum,jdbcType=BIT},
|
||||
#{createUser,jdbcType=VARCHAR}, #{systemId,jdbcType=VARCHAR})
|
||||
#{createUser,jdbcType=VARCHAR}, #{systemId,jdbcType=VARCHAR}, #{mockTcpPort,jdbcType=INTEGER},
|
||||
#{isMockTcpOpen,jdbcType=BIT})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.Project">
|
||||
insert into project
|
||||
|
@ -181,6 +185,12 @@
|
|||
<if test="systemId != null">
|
||||
system_id,
|
||||
</if>
|
||||
<if test="mockTcpPort != null">
|
||||
mock_tcp_port,
|
||||
</if>
|
||||
<if test="isMockTcpOpen != null">
|
||||
is_mock_tcp_open,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -234,6 +244,12 @@
|
|||
<if test="systemId != null">
|
||||
#{systemId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="mockTcpPort != null">
|
||||
#{mockTcpPort,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="isMockTcpOpen != null">
|
||||
#{isMockTcpOpen,jdbcType=BIT},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.ProjectExample" resultType="java.lang.Long">
|
||||
|
@ -296,6 +312,12 @@
|
|||
<if test="record.systemId != null">
|
||||
system_id = #{record.systemId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.mockTcpPort != null">
|
||||
mock_tcp_port = #{record.mockTcpPort,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.isMockTcpOpen != null">
|
||||
is_mock_tcp_open = #{record.isMockTcpOpen,jdbcType=BIT},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -319,7 +341,9 @@
|
|||
custom_num = #{record.customNum,jdbcType=BIT},
|
||||
scenario_custom_num = #{record.scenarioCustomNum,jdbcType=BIT},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
system_id = #{record.systemId,jdbcType=VARCHAR}
|
||||
system_id = #{record.systemId,jdbcType=VARCHAR},
|
||||
mock_tcp_port = #{record.mockTcpPort,jdbcType=INTEGER},
|
||||
is_mock_tcp_open = #{record.isMockTcpOpen,jdbcType=BIT}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -375,6 +399,12 @@
|
|||
<if test="systemId != null">
|
||||
system_id = #{systemId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="mockTcpPort != null">
|
||||
mock_tcp_port = #{mockTcpPort,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="isMockTcpOpen != null">
|
||||
is_mock_tcp_open = #{isMockTcpOpen,jdbcType=BIT},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -395,7 +425,9 @@
|
|||
custom_num = #{customNum,jdbcType=BIT},
|
||||
scenario_custom_num = #{scenarioCustomNum,jdbcType=BIT},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
system_id = #{systemId,jdbcType=VARCHAR}
|
||||
system_id = #{systemId,jdbcType=VARCHAR},
|
||||
mock_tcp_port = #{mockTcpPort,jdbcType=INTEGER},
|
||||
is_mock_tcp_open = #{isMockTcpOpen,jdbcType=BIT}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -0,0 +1,10 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtMockExpectConfigMapper {
|
||||
|
||||
List<MockExpectConfigWithBLOBs> selectByProjectIdAndStatusIsOpen(String projectId);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtMockExpectConfigMapper">
|
||||
|
||||
<select id="selectByProjectIdAndStatusIsOpen" resultType="io.metersphere.base.domain.MockExpectConfigWithBLOBs">
|
||||
SELECT * FROM mock_expect_config WHERE status = 'true' AND mock_config_id IN
|
||||
(SELECT id FROM mock_config WHERE api_path IS NULL AND project_id = #{0} )
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -34,7 +34,7 @@
|
|||
<select id="getProjectWithWorkspace" resultType="io.metersphere.dto.ProjectDTO">
|
||||
select p.id, p.workspace_id, p.name, p.description, p.update_time, p.issue_template_id, p.case_template_id,
|
||||
p.create_time, w.id as workspaceId, w.name as workspaceName, p.tapd_id, p.jira_key, p.zentao_id,p.azure_devops_id,p.repeatable, p.custom_num,
|
||||
user.name as createUserName,
|
||||
user.name as createUserName,p.mock_tcp_port AS mockTcpPort,p.is_mock_tcp_open AS isMockTcpOpen,
|
||||
p.scenario_custom_num
|
||||
from project p
|
||||
join workspace w on p.workspace_id = w.id
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONPath;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -131,116 +130,4 @@ public class JsonPathUtils {
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查一个JSON对象的数据是否被另一个对象匹配(包含)
|
||||
*
|
||||
* @param sourceObj 目标JSON
|
||||
* @param matchObj 要进行匹配的JSON
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkJsonObjCompliance(JSONObject sourceObj, JSONObject matchObj) {
|
||||
if (sourceObj == null && matchObj == null) {
|
||||
return true;
|
||||
} else if (sourceObj != null && matchObj != null) {
|
||||
boolean isMatch = false;
|
||||
try {
|
||||
Set<String> matchKeys = matchObj.keySet();
|
||||
for (String key : matchKeys) {
|
||||
if (sourceObj.containsKey(key)) {
|
||||
Object sourceObjItem = sourceObj.get(key);
|
||||
Object matchObjItem = matchObj.get(key);
|
||||
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return isMatch;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查一个JSON对象的数据集合是否包含另一个对象(包含)
|
||||
* @param sourceArray
|
||||
* @param matchObj
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONObject matchObj) {
|
||||
if (sourceArray == null && matchObj == null) {
|
||||
return true;
|
||||
} else if (sourceArray != null && matchObj != null) {
|
||||
boolean isMatch = false;
|
||||
try {
|
||||
Set<String> matchKeys = matchObj.keySet();
|
||||
for(int sourceIndex = 0;sourceIndex < sourceArray.size();sourceIndex ++){
|
||||
JSONObject sourceObj = sourceArray.getJSONObject(sourceIndex);
|
||||
for (String key : matchKeys) {
|
||||
if (sourceObj.containsKey(key)) {
|
||||
Object sourceObjItem = sourceObj.get(key);
|
||||
Object matchObjItem = matchObj.get(key);
|
||||
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
|
||||
if(!isMatch){
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
isMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isMatch){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return isMatch;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkObjCompliance(Object sourceObjItem, Object matchObjItem) {
|
||||
if (matchObjItem instanceof JSONObject) {
|
||||
if (sourceObjItem instanceof JSONObject) {
|
||||
return checkJsonObjCompliance((JSONObject) sourceObjItem, (JSONObject) matchObjItem);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (matchObjItem instanceof JSONArray) {
|
||||
if (sourceObjItem instanceof JSONArray) {
|
||||
JSONArray sourceArr = (JSONArray) sourceObjItem;
|
||||
JSONArray matchArr = (JSONArray) matchObjItem;
|
||||
//同是arr 可能顺序存在不同。 所以需要循环匹配
|
||||
if (matchArr.size() > sourceArr.size()) {
|
||||
return false;
|
||||
} else {
|
||||
for (int i = 0; i < matchArr.size(); i++) {
|
||||
for (int j = i; j < sourceArr.size(); j++) {
|
||||
Object matchItemObj = matchArr.get(i);
|
||||
Object sourceItemObj = sourceArr.get(j);
|
||||
boolean check = checkObjCompliance(sourceItemObj, matchItemObj);
|
||||
if (!check) {
|
||||
return check;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
String sourceValues = String.valueOf(sourceObjItem);
|
||||
String matchValues = String.valueOf(matchObjItem);
|
||||
return StringUtils.equals(sourceValues, matchValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONValidator;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* JSON数据结构相关的工具类
|
||||
* @author song.tianyang
|
||||
* @Date 2021/8/16 3:50 下午
|
||||
*/
|
||||
public class JsonStructUtils {
|
||||
|
||||
/**
|
||||
* 检查一个JSON对象的数据是否被另一个对象匹配(包含)
|
||||
*
|
||||
* @param sourceObj 目标JSON
|
||||
* @param matchObj 要进行匹配的JSON
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkJsonObjCompliance(JSONObject sourceObj, JSONObject matchObj) {
|
||||
if (sourceObj == null && matchObj == null) {
|
||||
return true;
|
||||
} else if (sourceObj != null && matchObj != null) {
|
||||
boolean isMatch = false;
|
||||
try {
|
||||
Set<String> matchKeys = matchObj.keySet();
|
||||
for (String key : matchKeys) {
|
||||
if (sourceObj.containsKey(key)) {
|
||||
Object sourceObjItem = sourceObj.get(key);
|
||||
Object matchObjItem = matchObj.get(key);
|
||||
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return isMatch;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONArray matchArray) {
|
||||
if (sourceArray == null && matchArray == null) {
|
||||
return true;
|
||||
} else if (sourceArray != null && matchArray != null && sourceArray.size() > matchArray.size()) {
|
||||
try {
|
||||
for (int i = 0; i < matchArray.size(); i ++) {
|
||||
Object obj = matchArray.get(i);
|
||||
if(!sourceArray.contains(obj)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkJsonArrayContainsObj(JSONArray sourceArray, JSONObject matchObj) {
|
||||
if (sourceArray == null && matchObj == null) {
|
||||
return true;
|
||||
} else if (sourceArray != null && matchObj != null ) {
|
||||
try {
|
||||
for (int i = 0; i < sourceArray.size(); i ++) {
|
||||
Object obj = sourceArray.get(i);
|
||||
if(obj instanceof JSONObject){
|
||||
boolean isMatch = checkJsonObjCompliance((JSONObject) obj,matchObj);
|
||||
if(isMatch){
|
||||
return isMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查一个JSON对象的数据集合是否包含另一个对象(包含)
|
||||
* @param sourceArray
|
||||
* @param matchObj
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONObject matchObj) {
|
||||
if (sourceArray == null && matchObj == null) {
|
||||
return true;
|
||||
} else if (sourceArray != null && matchObj != null) {
|
||||
boolean isMatch = false;
|
||||
try {
|
||||
Set<String> matchKeys = matchObj.keySet();
|
||||
for(int sourceIndex = 0;sourceIndex < sourceArray.size();sourceIndex ++){
|
||||
JSONObject sourceObj = sourceArray.getJSONObject(sourceIndex);
|
||||
for (String key : matchKeys) {
|
||||
if (sourceObj.containsKey(key)) {
|
||||
Object sourceObjItem = sourceObj.get(key);
|
||||
Object matchObjItem = matchObj.get(key);
|
||||
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
|
||||
if(!isMatch){
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
isMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isMatch){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return isMatch;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkObjCompliance(Object sourceObjItem, Object matchObjItem) {
|
||||
if (matchObjItem instanceof JSONObject) {
|
||||
if (sourceObjItem instanceof JSONObject) {
|
||||
return checkJsonObjCompliance((JSONObject) sourceObjItem, (JSONObject) matchObjItem);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (matchObjItem instanceof JSONArray) {
|
||||
if (sourceObjItem instanceof JSONArray) {
|
||||
JSONArray sourceArr = (JSONArray) sourceObjItem;
|
||||
JSONArray matchArr = (JSONArray) matchObjItem;
|
||||
//同是arr 可能顺序存在不同。 所以需要循环匹配
|
||||
if (matchArr.size() > sourceArr.size()) {
|
||||
return false;
|
||||
} else {
|
||||
for (int i = 0; i < matchArr.size(); i++) {
|
||||
for (int j = i; j < sourceArr.size(); j++) {
|
||||
Object matchItemObj = matchArr.get(i);
|
||||
Object sourceItemObj = sourceArr.get(j);
|
||||
boolean check = checkObjCompliance(sourceItemObj, matchItemObj);
|
||||
if (!check) {
|
||||
return check;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
String sourceValues = String.valueOf(sourceObjItem);
|
||||
String matchValues = String.valueOf(matchObjItem);
|
||||
return StringUtils.equals(sourceValues, matchValues);
|
||||
}
|
||||
}
|
||||
|
||||
public static void deepParseKeyByJsonObject(JSONObject jsonObject, List<String> keyList) {
|
||||
for (String key : jsonObject.keySet()) {
|
||||
Object obj = jsonObject.get(key);
|
||||
if(obj instanceof JSONArray) {
|
||||
deepParseKeyByJsonArray((JSONArray) obj, keyList);
|
||||
}else if(obj instanceof JSONObject){
|
||||
deepParseKeyByJsonObject((JSONObject) obj,keyList);
|
||||
}else {
|
||||
if(!keyList.contains(key)){
|
||||
keyList.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void deepParseKeyByJsonArray(JSONArray jsonArray, List<String> keyList) {
|
||||
for (int i = 0; i < jsonArray.size(); i ++) {
|
||||
Object itemObj = jsonArray.get(i);
|
||||
if(itemObj instanceof JSONObject){
|
||||
deepParseKeyByJsonObject((JSONObject)itemObj,keyList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkJsonCompliance(String sourceJson, String matchJson) {
|
||||
boolean isMatch = false;
|
||||
try {
|
||||
boolean isSourceJsonIsArray = false;
|
||||
boolean isMatchJsonIsArray = false;
|
||||
|
||||
JSONValidator sourceValidator = JSONValidator.from(sourceJson);
|
||||
JSONValidator matchValidator = JSONValidator.from(matchJson);
|
||||
String sourceType = sourceValidator.getType().name();
|
||||
String matchType = matchValidator.getType().name();
|
||||
if(StringUtils.equalsIgnoreCase(sourceType,"array")&&StringUtils.equalsIgnoreCase(matchType,"array")){
|
||||
isSourceJsonIsArray = true;
|
||||
isMatchJsonIsArray = true;
|
||||
}else if(StringUtils.equalsIgnoreCase(sourceType,"array")){
|
||||
isSourceJsonIsArray = true;
|
||||
}else if(StringUtils.equalsIgnoreCase(matchType,"array")){
|
||||
isMatchJsonIsArray = true;
|
||||
}
|
||||
if(isSourceJsonIsArray && isMatchJsonIsArray){
|
||||
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
|
||||
JSONArray compArr = JSONArray.parseArray(matchJson);
|
||||
isMatch = checkJsonArrayCompliance(sourceArr,compArr);
|
||||
}else if(isSourceJsonIsArray && !isMatchJsonIsArray){
|
||||
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
|
||||
JSONObject compObj = JSONObject.parseObject(matchJson);
|
||||
isMatch = checkJsonArrayContainsObj(sourceArr,compObj);
|
||||
}else if(!isSourceJsonIsArray && !isMatchJsonIsArray){
|
||||
JSONObject sourceObj = JSONObject.parseObject(sourceJson);
|
||||
JSONObject compObj = JSONObject.parseObject(matchJson);
|
||||
isMatch = checkJsonObjCompliance(sourceObj,compObj);
|
||||
}else {
|
||||
isMatch = false;
|
||||
}
|
||||
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
return isMatch;
|
||||
}
|
||||
}
|
|
@ -73,15 +73,8 @@ public class ProjectController {
|
|||
@MsAuditLog(module = "project_project_manager", type = OperLogConstants.CREATE, content = "#msClass.getLogDetails(#project.id)", msClass = ProjectService.class)
|
||||
public Project addProject(@RequestBody AddProjectRequest project, HttpServletRequest request) {
|
||||
Project returnModel = projectService.addProject(project);
|
||||
|
||||
//创建项目的时候默认增加Mock环境
|
||||
String requestUrl = request.getRequestURL().toString();
|
||||
String baseUrl = "";
|
||||
if (requestUrl.contains("/project/add")) {
|
||||
baseUrl = requestUrl.split("/project/add")[0];
|
||||
}
|
||||
apiTestEnvironmentService.getMockEnvironmentByProjectId(returnModel.getId(), project.getProtocal(), baseUrl);
|
||||
|
||||
apiTestEnvironmentService.getMockEnvironmentByProjectId(returnModel.getId());
|
||||
return returnModel;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.metersphere.commons.utils.LogUtil;
|
|||
import io.metersphere.commons.utils.RunInterface;
|
||||
import io.metersphere.performance.service.PerformanceTestService;
|
||||
import io.metersphere.service.JarConfigService;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.service.ScheduleService;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
import io.metersphere.track.service.IssuesService;
|
||||
|
@ -38,6 +39,8 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
|||
@Resource
|
||||
private IssuesService issuesService;
|
||||
@Resource
|
||||
private ProjectService projectService;
|
||||
@Resource
|
||||
private PerformanceTestService performanceTestService;
|
||||
@Value("${jmeter.home}")
|
||||
private String jmeterHome;
|
||||
|
@ -53,6 +56,8 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
|||
|
||||
initPythonEnv();
|
||||
|
||||
projectService.initMockTcpService();
|
||||
|
||||
initOperate(apiAutomationService::checkApiScenarioUseUrl, "init.scenario.url");
|
||||
initOperate(apiAutomationService::checkApiScenarioReferenceId, "init.scenario.referenceId");
|
||||
initOperate(issuesService::syncThirdPartyIssues, "init.issue");
|
||||
|
@ -66,6 +71,7 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
|||
}
|
||||
|
||||
scheduleService.startEnableSchedules();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ import io.metersphere.api.dto.DeleteAPITestRequest;
|
|||
import io.metersphere.api.dto.QueryAPITestRequest;
|
||||
import io.metersphere.api.service.APITestService;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
import io.metersphere.api.service.ApiTestEnvironmentService;
|
||||
import io.metersphere.api.tcp.TCPPool;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtOrganizationMapper;
|
||||
|
@ -13,6 +15,7 @@ import io.metersphere.base.mapper.ext.ExtUserGroupMapper;
|
|||
import io.metersphere.base.mapper.ext.ExtUserMapper;
|
||||
import io.metersphere.commons.constants.UserGroupConstants;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.request.ProjectRequest;
|
||||
|
@ -186,6 +189,9 @@ public class ProjectService {
|
|||
// User Group
|
||||
deleteProjectUserGroup(projectId);
|
||||
|
||||
//关闭TCP
|
||||
this.closeMockTcp(projectId);
|
||||
|
||||
// delete project
|
||||
projectMapper.deleteByPrimaryKey(projectId);
|
||||
|
||||
|
@ -260,6 +266,15 @@ public class ProjectService {
|
|||
}
|
||||
|
||||
public void updateProject(Project project) {
|
||||
//查询之前的TCP端口,用于检查是否需要开启/关闭 TCP接口
|
||||
int lastTcpNum = 0;
|
||||
Project oldData = projectMapper.selectByPrimaryKey(project.getId());
|
||||
if(oldData!=null && oldData.getMockTcpPort() != null){
|
||||
lastTcpNum = oldData.getMockTcpPort().intValue();
|
||||
}
|
||||
|
||||
this.checkProjectTcpPort(project);
|
||||
|
||||
project.setCreateTime(null);
|
||||
project.setUpdateTime(System.currentTimeMillis());
|
||||
checkProjectExist(project);
|
||||
|
@ -267,6 +282,28 @@ public class ProjectService {
|
|||
testCaseService.updateTestCaseCustomNumByProjectId(project.getId());
|
||||
}
|
||||
projectMapper.updateByPrimaryKeySelective(project);
|
||||
|
||||
//检查Mock环境是否需要同步更新
|
||||
ApiTestEnvironmentService apiTestEnvironmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
||||
apiTestEnvironmentService.getMockEnvironmentByProjectId(project.getId());
|
||||
//开启tcp mock
|
||||
if(project.getIsMockTcpOpen()){
|
||||
this.reloadMockTcp(project,lastTcpNum);
|
||||
}else {
|
||||
this.closeMockTcp(project);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkProjectTcpPort(Project project) {
|
||||
//判断端口是否重复
|
||||
if(project.getMockTcpPort() != null && project.getMockTcpPort().intValue() != 0){
|
||||
ProjectExample example = new ProjectExample();
|
||||
example.createCriteria().andMockTcpPortEqualTo(project.getMockTcpPort());
|
||||
long countResult = projectMapper.countByExample(example);
|
||||
if(countResult > 0){
|
||||
MSException.throwException("TCP Port is not unique!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkProjectExist(Project project) {
|
||||
|
@ -483,4 +520,54 @@ public class ProjectService {
|
|||
public Map<String, Project> queryNameByIds(List<String> ids) {
|
||||
return extProjectMapper.queryNameByIds(ids);
|
||||
}
|
||||
|
||||
public void openMockTcp(Project project){
|
||||
if(project == null){
|
||||
MSException.throwException("Project not found!");
|
||||
}else {
|
||||
if(project.getMockTcpPort() == null){
|
||||
MSException.throwException("Mock tcp port is not Found!");
|
||||
}else {
|
||||
TCPPool.createTcp(project.getMockTcpPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
public void reloadMockTcp(Project project,int oldPort){
|
||||
this.closeMockTcp(oldPort);
|
||||
this.openMockTcp(project);
|
||||
}
|
||||
|
||||
public void closeMockTcp(String projectId){
|
||||
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||
this.closeMockTcp(project);
|
||||
}
|
||||
public void closeMockTcp(Project project){
|
||||
if(project == null){
|
||||
MSException.throwException("Project not found!");
|
||||
}else {
|
||||
if(project.getMockTcpPort() == null){
|
||||
MSException.throwException("Mock tcp port is not Found!");
|
||||
}else {
|
||||
this.closeMockTcp(project.getMockTcpPort().intValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void closeMockTcp(int tcpPort){
|
||||
if(tcpPort != 0){
|
||||
TCPPool.closeTcp(tcpPort);
|
||||
}
|
||||
}
|
||||
|
||||
public void initMockTcpService() {
|
||||
ProjectExample example = new ProjectExample();
|
||||
Integer portInteger = new Integer(0);
|
||||
Boolean statusBoolean = new Boolean(true);
|
||||
example.createCriteria().andIsMockTcpOpenEqualTo(statusBoolean).andMockTcpPortNotEqualTo(portInteger);
|
||||
List<Project> projectList = projectMapper.selectByExample(example);
|
||||
|
||||
for (Project p :projectList) {
|
||||
this.openMockTcp(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ CREATE TABLE IF NOT EXISTS `mock_expect_config`
|
|||
`tags` varchar(1000) null,
|
||||
request longtext null,
|
||||
response longtext null,
|
||||
STATUS VARCHAR(10) null,
|
||||
status VARCHAR(10) null,
|
||||
create_time bigint(13) null,
|
||||
update_time bigint(13) null,
|
||||
create_user_id VARCHAR(64) null,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<el-button plain :class="{active: showTestCaseList}" @click="changeTab('testCase')" size="small">CASE</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip class="item" effect="dark" content="Mock设置" placement="right" v-if="currentProtocol==='HTTP'">
|
||||
<el-tooltip class="item" effect="dark" content="Mock设置" placement="right" v-if="currentProtocol === 'HTTP' || currentProtocol === 'TCP'">
|
||||
<el-button plain :class="{active: showMock}" @click="changeTab('mock')" size="small"> Mock</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
|
@ -72,8 +72,11 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="showMock" class="ms-api-div">
|
||||
<mock-config :base-mock-config-data="baseMockConfigData"/>
|
||||
<div v-if="showMock && (currentProtocol === 'HTTP')" class="ms-api-div">
|
||||
<mock-config :base-mock-config-data="baseMockConfigData" type="http"/>
|
||||
</div>
|
||||
<div v-if="showMock && (currentProtocol === 'TCP')" class="ms-api-div">
|
||||
<tcp-mock-config :base-mock-config-data="baseMockConfigData" type="tcp"/>
|
||||
</div>
|
||||
<div v-if="showTestCaseList">
|
||||
<!--测试用例列表-->
|
||||
|
@ -96,6 +99,7 @@ import MsRunTestTcpPage from "./runtest/RunTestTCPPage";
|
|||
import MsRunTestSqlPage from "./runtest/RunTestSQLPage";
|
||||
import MsRunTestDubboPage from "./runtest/RunTestDubboPage";
|
||||
import MockConfig from "@/business/components/api/definition/components/mock/MockConfig";
|
||||
import TcpMockConfig from "@/business/components/api/definition/components/mock/TcpMockConfig";
|
||||
import ApiCaseSimpleList from "./list/ApiCaseSimpleList";
|
||||
|
||||
export default {
|
||||
|
@ -107,6 +111,7 @@ export default {
|
|||
MsRunTestSqlPage,
|
||||
MsRunTestDubboPage,
|
||||
MockConfig,
|
||||
TcpMockConfig,
|
||||
ApiCaseSimpleList
|
||||
},
|
||||
data() {
|
||||
|
@ -139,7 +144,7 @@ export default {
|
|||
},
|
||||
created() {
|
||||
this.refreshButtonActiveClass(this.activeDom);
|
||||
if (this.currentApi.id !== null && this.currentProtocol === "HTTP") {
|
||||
if (this.currentApi.id !== null && (this.currentProtocol === "HTTP" || this.currentProtocol === "TCP")) {
|
||||
this.mockSetting();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -21,6 +21,21 @@
|
|||
@changeApiProtocol="changeApiProtocol" @callback="callback"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- MOCK信息 -->
|
||||
<p class="tip">{{ $t('test_track.plan_view.mock_info') }} </p>
|
||||
<div class="mock-info">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
Mock地址:
|
||||
<el-link v-if="this.mockInfo !== '' " target="_blank" style="color: black"
|
||||
type="primary">{{ this.mockInfo }}
|
||||
</el-link>
|
||||
<el-link v-else target="_blank" style="color: darkred"
|
||||
type="primary">当前项目未开启Mock服务
|
||||
</el-link>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 请求参数 -->
|
||||
<div v-if="apiProtocol=='TCP'">
|
||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||
|
@ -45,7 +60,7 @@
|
|||
import MsTcpBasicApi from "./TCPBasicApi";
|
||||
import MsTcpFormatParameters from "../request/tcp/TcpFormatParameters";
|
||||
import MsChangeHistory from "../../../../history/ChangeHistory";
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
import {hasLicense,getCurrentProjectID} from "@/common/js/utils";
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const esbDefinition = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {};
|
||||
|
@ -69,6 +84,7 @@ export default {
|
|||
return {
|
||||
validated: false,
|
||||
apiProtocol: "TCP",
|
||||
mockInfo: "",
|
||||
methodTypes:[
|
||||
{
|
||||
'key':"TCP",
|
||||
|
@ -96,8 +112,8 @@ export default {
|
|||
this.methodTypes.push(esbMethodType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.getMockInfo();
|
||||
},
|
||||
watch: {
|
||||
syncTabs() {
|
||||
|
@ -191,11 +207,19 @@ export default {
|
|||
},
|
||||
changeApiProtocol(protocol){
|
||||
this.apiProtocol = protocol;
|
||||
}
|
||||
},
|
||||
getMockInfo(){
|
||||
let projectId = getCurrentProjectID();
|
||||
this.$get("/api/environment/getTcpMockInfo/" + projectId, response => {
|
||||
this.mockInfo = response.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.mock-info {
|
||||
margin: 20px 45px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,361 @@
|
|||
<template>
|
||||
<div class="card-container">
|
||||
<el-card class="card-content" v-loading="mockConfigData.loading">
|
||||
<p class="tip">期望列表</p>
|
||||
<div class="card">
|
||||
<el-input :placeholder="$t('commons.search_by_name')" class="search-input" size="small"
|
||||
:clearable="serchInputClearable"
|
||||
v-model="tableSearch"/>
|
||||
<el-table ref="table" border
|
||||
:data="mockConfigData.mockExpectConfigList.filter(data=>!tableSearch || data.name.toLowerCase().includes(tableSearch.toLowerCase()))"
|
||||
@row-click="clickRow"
|
||||
row-key="id" class="test-content" :height="screenHeight">
|
||||
<el-table-column :label="$t('api_test.mock.table.name')" min-width="160px" prop="name"></el-table-column>
|
||||
<el-table-column :label="$t('api_test.mock.table.tag')" min-width="200px" prop="tags">
|
||||
<template v-slot:default="scope">
|
||||
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
|
||||
:show-tooltip="true" :content="itemName"
|
||||
style="margin-left: 0px; margin-right: 2px"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('api_test.mock.table.creator')" min-width="160px"
|
||||
prop="createUserId"></el-table-column>
|
||||
<el-table-column :label="$t('api_test.mock.table.status')" min-width="80px" prop="status">
|
||||
<template v-slot:default="scope">
|
||||
<div>
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
class="captcha-img"
|
||||
@change="changeStatus(scope.row)"
|
||||
></el-switch>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('api_test.mock.table.update_time')" min-width="160px" prop="updateTime">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" min-width="100" align="center" :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<div>
|
||||
<ms-table-operator-button :tip="$t('commons.copy')" icon="el-icon-copy-document"
|
||||
@exec="copyExpect(scope.row)"
|
||||
/>
|
||||
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete"
|
||||
@exec="removeExpect(scope.row)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 期望详情 -->
|
||||
<p class="tip">{{ $t('api_test.mock.expect_detail') }}</p>
|
||||
<el-form :model="mockExpectConfig" :rules="rule" ref="mockExpectForm" label-width="80px" label-position="right">
|
||||
<div class="card">
|
||||
<div class="base-info">
|
||||
<el-row>
|
||||
<el-col>{{ $t('api_test.mock.base_info') }}</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.name')" prop="name">
|
||||
<el-input class="ms-http-input" size="small" v-model="mockExpectConfig.name"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.tag')" prop="tag">
|
||||
<ms-input-tag :currentScenario="mockExpectConfig" v-if="showHeadTable" ref="tag"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col>{{ $t('api_test.mock.req_param') }}</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<tcp-params :request="mockExpectConfig.request" style="margin: 10px 10px;" ref="tcpParam"></tcp-params>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 10px;">
|
||||
<el-col>{{ $t('api_test.mock.rsp_param') }}</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-form-item label="延时 (ms)" prop="response.delayed">
|
||||
<el-input-number v-model="mockExpectConfig.response.delayed" :min="0">
|
||||
<template slot="append">ms</template>
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 10px;">
|
||||
<el-form-item label="Body:" label-width="50px">
|
||||
<ms-code-edit height="200px" :mode="'txt'" ref="codeEdit" :data.sync="mockExpectConfig.response.body"
|
||||
style="margin-top: 10px;"/>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div style="float: right;margin-right: 20px">
|
||||
<el-button type="primary" size="small" @click="saveMockExpectConfig" title="ctrl + s">{{
|
||||
$t('commons.add')
|
||||
}}
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" @click="cleanMockExpectConfig">{{
|
||||
$t('commons.clear')
|
||||
}}
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" v-if="mockExpectConfig.id != '' && mockExpectConfig.id != null"
|
||||
@click="updateMockExpectConfig">{{ $t('commons.update') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton";
|
||||
import MockRowVariables from "@/business/components/api/definition/components/mock/MockRowVariables";
|
||||
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
|
||||
import MsCodeEdit from "@/business/components/api/definition/components/MsCodeEdit";
|
||||
import MsApiVariableAdvance from "@/business/components/api/test/components/ApiVariableAdvance";
|
||||
import MsTag from "@/business/components/common/components/MsTag";
|
||||
import {REQUEST_HEADERS} from "@/common/js/constants";
|
||||
import TcpParams from "@/business/components/api/definition/components/request/tcp/TcpParams";
|
||||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
|
||||
|
||||
export default {
|
||||
name: "TcpMockConfig",
|
||||
components: {
|
||||
MockRowVariables,
|
||||
MsTableOperatorButton,
|
||||
MsInputTag,
|
||||
MsCodeEdit,
|
||||
MsApiVariableAdvance,
|
||||
TcpParams,
|
||||
MsTag,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
screenHeight: 300,
|
||||
tableSearch: "",
|
||||
showHeadTable: true,
|
||||
serchInputClearable: true,
|
||||
mockConfigData: {},
|
||||
apiParams: [],
|
||||
headerSuggestions: REQUEST_HEADERS,
|
||||
mockExpectConfig: {
|
||||
id: "",
|
||||
name: "",
|
||||
mockConfigId: "",
|
||||
request: {
|
||||
reportType:'raw',
|
||||
xmlDataStruct:[],
|
||||
},
|
||||
response: {
|
||||
httpCode: "",
|
||||
delayed: "",
|
||||
httpHeads: [],
|
||||
body: "",
|
||||
},
|
||||
},
|
||||
rule: {
|
||||
name: [
|
||||
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
|
||||
{max: 100, message: this.$t('test_track.length_less_than') + '100', trigger: 'blur'}
|
||||
],
|
||||
response: {
|
||||
httpCode: [{required: true, message: this.$t('api_test.mock.rule.input_code'), trigger: 'blur'},],
|
||||
delayed: [{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},],
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
props: {
|
||||
baseMockConfigData: {},
|
||||
type:String
|
||||
},
|
||||
created() {
|
||||
this.mockConfigData = this.baseMockConfigData;
|
||||
this.searchApiParams(this.mockConfigData.mockConfig.apiId);
|
||||
},
|
||||
methods: {
|
||||
searchApiParams(apiId) {
|
||||
let selectUrl = "/mockConfig/getApiParams/" + apiId;
|
||||
this.$get(selectUrl, response => {
|
||||
this.apiParams = response.data;
|
||||
});
|
||||
},
|
||||
copyExpect(row) {
|
||||
let selectUrl = "/mockConfig/mockExpectConfig/" + row.id;
|
||||
this.$get(selectUrl, response => {
|
||||
let data = response.data;
|
||||
this.showHeadTable = false;
|
||||
this.mockExpectConfig = data;
|
||||
this.mockExpectConfig.id = "";
|
||||
this.mockExpectConfig.name = this.mockExpectConfig.name + "_copy";
|
||||
if (this.mockExpectConfig.request == null) {
|
||||
this.mockExpectConfig.request = {
|
||||
jsonParam: false,
|
||||
variables: [],
|
||||
jsonData: "{}",
|
||||
};
|
||||
}
|
||||
if (this.mockExpectConfig.response == null) {
|
||||
this.mockExpectConfig.response = {
|
||||
httpCode: "",
|
||||
delayed: "",
|
||||
httpHeads: [],
|
||||
body: "",
|
||||
};
|
||||
}
|
||||
this.$nextTick(function () {
|
||||
this.showHeadTable = true;
|
||||
this.saveMockExpectConfig();
|
||||
});
|
||||
});
|
||||
},
|
||||
removeExpect(row) {
|
||||
this.$confirm(this.$t('api_test.mock.delete_mock_expect'), this.$t('commons.prompt'), {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let mockInfoId = row.mockConfigId;
|
||||
let selectUrl = "/mockConfig/deleteMockExpectConfig/" + row.id;
|
||||
this.$get(selectUrl, response => {
|
||||
this.cleanMockExpectConfig();
|
||||
this.refreshMockInfo(mockInfoId);
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('commons.delete_success'),
|
||||
});
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
|
||||
},
|
||||
saveMockExpectConfig() {
|
||||
let mockConfigId = this.mockConfigData.mockConfig.id;
|
||||
this.mockExpectConfig.mockConfigId = mockConfigId;
|
||||
this.mockExpectConfig.id = "";
|
||||
let formCheckResult = this.checkMockExpectForm("mockExpectForm", true);
|
||||
},
|
||||
cleanMockExpectConfig() {
|
||||
this.showHeadTable = false;
|
||||
this.mockExpectConfig = {
|
||||
id: "",
|
||||
name: "",
|
||||
mockConfigId: "",
|
||||
request: {
|
||||
reportType:'raw',
|
||||
xmlDataStruct:[],
|
||||
},
|
||||
response: {
|
||||
httpCode: "",
|
||||
delayed: "",
|
||||
httpHeads: [],
|
||||
body: "",
|
||||
},
|
||||
};
|
||||
this.$nextTick(function () {
|
||||
this.showHeadTable = true;
|
||||
});
|
||||
},
|
||||
updateMockExpectConfig() {
|
||||
this.checkMockExpectForm("mockExpectForm");
|
||||
},
|
||||
uploadMockExpectConfig(clearForm) {
|
||||
let url = "/mockConfig/updateMockExpectConfig";
|
||||
let param = this.mockExpectConfig;
|
||||
this.$post(url, param, response => {
|
||||
let returnData = response.data;
|
||||
this.mockExpectConfig.id = returnData.id;
|
||||
this.refreshMockInfo(param.mockConfigId);
|
||||
if (clearForm) {
|
||||
this.cleanMockExpectConfig();
|
||||
}
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('commons.save_success'),
|
||||
});
|
||||
});
|
||||
},
|
||||
refreshMockInfo(mockConfigId) {
|
||||
let mockParam = {};
|
||||
mockParam.id = mockConfigId;
|
||||
this.$post('/mockConfig/genMockConfig', mockParam, response => {
|
||||
this.mockConfigData = response.data;
|
||||
});
|
||||
},
|
||||
checkMockExpectForm(formName, clearForm) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.uploadMockExpectConfig(clearForm);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
changeStatus(row) {
|
||||
let mockParam = {};
|
||||
mockParam.id = row.id;
|
||||
mockParam.status = row.status;
|
||||
this.$post('/mockConfig/updateMockExpectConfig', mockParam, response => {
|
||||
});
|
||||
},
|
||||
clickRow(row, column, event) {
|
||||
let selectUrl = "/mockConfig/mockExpectConfig/" + row.id;
|
||||
this.$get(selectUrl, response => {
|
||||
let data = response.data;
|
||||
this.showHeadTable = false;
|
||||
this.mockExpectConfig = data;
|
||||
if (this.mockExpectConfig.request == null) {
|
||||
this.mockExpectConfig.request = {
|
||||
reportType:'raw',
|
||||
xmlDataStruct:[],
|
||||
};
|
||||
}
|
||||
if (this.mockExpectConfig.response == null) {
|
||||
this.mockExpectConfig.response = {
|
||||
httpCode: "",
|
||||
delayed: "",
|
||||
httpHeads: [],
|
||||
body: "",
|
||||
};
|
||||
}
|
||||
this.$nextTick(function () {
|
||||
this.showHeadTable = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search-input {
|
||||
float: right;
|
||||
width: 300px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.base-info .el-form-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.base-info .el-form-item >>> .el-form-item__content {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.base-info .ms-http-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,289 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-radio-group v-model="request.reportType" size="mini" style="margin: 10px 0px;">
|
||||
<el-radio :disabled="isReadOnly" label="json" @change="changeReportType">
|
||||
json
|
||||
</el-radio>
|
||||
<el-radio :disabled="isReadOnly" label="xml" @change="changeReportType">
|
||||
xml
|
||||
</el-radio>
|
||||
<el-radio :disabled="isReadOnly" label="raw" @change="changeReportType">
|
||||
raw
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<div style="min-width: 1200px;" v-if="request.reportType === 'xml'">
|
||||
<tcp-xml-table :table-data="request.xmlDataStruct" :show-options-button="true"
|
||||
@xmlTablePushRow="xmlTablePushRow"
|
||||
@initXmlTableData="initXmlTableData"
|
||||
@saveTableData="saveXmlTableData" ref="treeTable"></tcp-xml-table>
|
||||
</div>
|
||||
<div style="min-width: 1200px;" v-if="request.reportType === 'json'">
|
||||
<div class="send-request">
|
||||
<ms-code-edit mode="json" :read-only="isReadOnly" :data.sync="request.jsonDataStruct" :modes="['text', 'json', 'xml', 'html']" theme="eclipse"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="min-width: 1200px;" v-if="request.reportType === 'raw'">
|
||||
<div class="send-request">
|
||||
<ms-code-edit mode="text" :read-only="isReadOnly" :data.sync="request.rawDataStruct" :modes="['text', 'json', 'xml', 'html']" theme="eclipse"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsApiKeyValue from "../../ApiKeyValue";
|
||||
import MsApiAssertions from "../../assertion/ApiAssertions";
|
||||
import MsApiExtract from "../../extract/ApiExtract";
|
||||
import ApiRequestMethodSelect from "../../collapse/ApiRequestMethodSelect";
|
||||
import MsCodeEdit from "../../../../../common/components/MsCodeEdit";
|
||||
import MsApiScenarioVariables from "../../ApiScenarioVariables";
|
||||
import {createComponent} from "../../jmeter/components";
|
||||
import {Assertions, Extract} from "../../../model/ApiTestModel";
|
||||
import {parseEnvironment} from "../../../model/EnvironmentModel";
|
||||
import ApiEnvironmentConfig from "../../environment/ApiEnvironmentConfig";
|
||||
import {API_STATUS} from "../../../model/JsonData";
|
||||
import TCPSampler from "../../jmeter/components/sampler/tcp-sampler";
|
||||
import {getCurrentProjectID, getUUID} from "@/common/js/utils";
|
||||
import MsApiVariable from "../../ApiVariable";
|
||||
import MsInstructionsIcon from "../../../../../common/components/MsInstructionsIcon";
|
||||
import Jsr233ProcessorContent from "../../../../automation/scenario/common/Jsr233ProcessorContent";
|
||||
import JSR223PreProcessor from "../../jmeter/components/pre-processors/jsr223-pre-processor";
|
||||
import ApiDefinitionStepButton from "../components/ApiDefinitionStepButton";
|
||||
import TcpXmlTable from "@/business/components/api/definition/components/complete/table/TcpXmlTable";
|
||||
|
||||
|
||||
export default {
|
||||
name: "MsTcpParams",
|
||||
components: {
|
||||
TcpXmlTable,
|
||||
ApiDefinitionStepButton,
|
||||
Jsr233ProcessorContent,
|
||||
MsInstructionsIcon,
|
||||
MsApiVariable,
|
||||
MsApiScenarioVariables,
|
||||
MsCodeEdit,
|
||||
ApiRequestMethodSelect, MsApiExtract, MsApiAssertions, MsApiKeyValue, ApiEnvironmentConfig
|
||||
},
|
||||
props: {
|
||||
request: {},
|
||||
basisData: {},
|
||||
moduleOptions: Array,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showScript: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
referenced: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
reportType:"raw",
|
||||
isReloadData: false,
|
||||
refreshedXmlTable:true,
|
||||
currentProjectId: "",
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
reportType(){
|
||||
this.request.reportType = this.reportType;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.currentProjectId = getCurrentProjectID();
|
||||
if (!this.request.parameters) {
|
||||
this.$set(this.request, 'parameters', []);
|
||||
this.request.parameters = [];
|
||||
}
|
||||
if(!this.request.connectEncoding){
|
||||
this.request.connectEncoding = "UTF-8";
|
||||
}
|
||||
if(!this.request.reportType){
|
||||
this.request.reportType = 'raw';
|
||||
}
|
||||
if(!this.request.jsonDataStruct){
|
||||
this.request.jsonDataStruct = "";
|
||||
}
|
||||
if(!this.request.rawDataStruct){
|
||||
this.request.rawDataStruct = "";
|
||||
}
|
||||
if(!this.request.xmlDataStruct){
|
||||
this.request.xmlDataStruct = [];
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.isReloadData = true
|
||||
this.$nextTick(() => {
|
||||
this.isReloadData = false
|
||||
})
|
||||
},
|
||||
runTest() {
|
||||
|
||||
},
|
||||
changeReportType(){
|
||||
},
|
||||
getParmas(){
|
||||
return this.request;
|
||||
},
|
||||
|
||||
//以下是xml树形表格相关的方法
|
||||
updateXmlTableData(dataStruct){
|
||||
this.request.xmlDataStruct = dataStruct;
|
||||
},
|
||||
saveXmlTableData(dataStruct){
|
||||
let valedataResult = this.validateXmlDataStruct(dataStruct);
|
||||
if(valedataResult){
|
||||
this.request.xmlDataStruct = dataStruct;
|
||||
this.refreshXmlTable();
|
||||
}
|
||||
},
|
||||
validateXmlDataStruct(){
|
||||
if(this.request.xmlDataStruct){
|
||||
this.refreshXmlTableDataStruct(this.request.xmlDataStruct);
|
||||
let result = this.checkXmlTableDataStructData(this.request.xmlDataStruct);
|
||||
return result;
|
||||
}
|
||||
},
|
||||
refreshXmlTableDataStruct(dataStruct){
|
||||
if(dataStruct && dataStruct.length > 0){
|
||||
dataStruct.forEach( row => {
|
||||
row.status = "";
|
||||
if(row.children == null || row.children.length === 0){
|
||||
row.children = [];
|
||||
}else if(row.children.length>0){
|
||||
this.refreshXmlTableDataStruct(row.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
checkXmlTableDataStructData(dataStruct){
|
||||
let allCheckResult = true;
|
||||
if(dataStruct && dataStruct.length > 0){
|
||||
for(let i = 0;i<dataStruct.length;i++){
|
||||
let row = dataStruct[i];
|
||||
allCheckResult = this.$refs.treeTable.validateRowData(row);
|
||||
if(allCheckResult){
|
||||
if(row.children != null && row.children.length > 0){
|
||||
allCheckResult = this.checkXmlTableDataStructData(row.children);
|
||||
if(!allCheckResult){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return allCheckResult;
|
||||
},
|
||||
initXmlTableData(){
|
||||
if(this.request){
|
||||
this.request.xmlDataStruct = [];
|
||||
this.refreshXmlTable();
|
||||
}
|
||||
},
|
||||
xmlTableDataPushRow(newRow){
|
||||
if(this.request){
|
||||
if(!this.request.xmlDataStruct){
|
||||
this.request.xmlDataStruct = [];
|
||||
}
|
||||
this.request.xmlDataStruct.push(newRow);
|
||||
this.refreshXmlTable();
|
||||
}
|
||||
},
|
||||
xmlTableDataRemoveRow(row){
|
||||
if(this.request){
|
||||
if(this.request.xmlDataStruct){
|
||||
this.removeFromDataStruct(this.request.xmlDataStruct,row);
|
||||
this.refreshXmlTable();
|
||||
}
|
||||
}
|
||||
},
|
||||
removeFromDataStruct(dataStruct,row){
|
||||
if(!dataStruct || dataStruct.length === 0){
|
||||
return;
|
||||
}
|
||||
let rowIndex = dataStruct.indexOf(row);
|
||||
if(rowIndex >= 0){
|
||||
dataStruct.splice(rowIndex,1);
|
||||
}else {
|
||||
dataStruct.forEach( itemData => {
|
||||
if(!itemData.children && itemData.children.length > 0){
|
||||
this.removeFromDataStruct(itemData.children,row);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
refreshXmlTable(){
|
||||
this.refreshedXmlTable = true
|
||||
this.$nextTick(() => {
|
||||
this.refreshedXmlTable = false
|
||||
})
|
||||
},
|
||||
xmlTablePushRow(row){
|
||||
this.request.xmlDataStruct.push(row);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tcp >>> .el-input-number {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.send-request {
|
||||
padding: 0px 0;
|
||||
height: 300px;
|
||||
border: 1px #DCDFE6 solid;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ms-left-cell {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.ms-left-buttion {
|
||||
margin: 6px 0px 8px 30px;
|
||||
}
|
||||
|
||||
/deep/ .el-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.ms-left-cell {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.ms-left-buttion {
|
||||
margin: 6px 0px 8px 30px;
|
||||
}
|
||||
|
||||
/deep/ .el-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/deep/ .instructions-icon {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.request-tabs {
|
||||
margin: 20px;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.other-config {
|
||||
padding: 15px;
|
||||
}
|
||||
</style>
|
|
@ -88,7 +88,6 @@
|
|||
<el-input v-model="form.name" autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item :label-width="labelWidth" :label="$t('用例模板')" prop="caseTemplateId">
|
||||
<template-select :data="form" scene="API_CASE" prop="caseTemplateId" ref="caseTemplate"/>
|
||||
</el-form-item>
|
||||
|
@ -96,6 +95,10 @@
|
|||
<template-select :data="form" scene="ISSUE" prop="issueTemplateId" ref="issueTemplate"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label-width="labelWidth" label="TCP Mock Port">
|
||||
<el-input-number v-model="form.mockTcpPort" :controls="false" style="width: 30%;margin-right: 30px"></el-input-number>
|
||||
<el-switch v-model="form.isMockTcpOpen"></el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label-width="labelWidth" :label="$t('commons.description')" prop="description">
|
||||
<el-input :autosize="{ minRows: 2, maxRows: 4}" type="textarea" v-model="form.description"></el-input>
|
||||
|
|
Loading…
Reference in New Issue