This commit is contained in:
chenjianxing 2020-07-17 18:26:00 +08:00
commit f20c9ca591
31 changed files with 1360 additions and 74 deletions

View File

@ -18,6 +18,8 @@
<shiro.version>1.5.1</shiro.version>
<java.version>1.8</java.version>
<jmeter.version>5.2.1</jmeter.version>
<nacos.version>1.1.3</nacos.version>
<dubbo.version>2.7.7</dubbo.version>
</properties>
<dependencies>
@ -154,6 +156,44 @@
</exclusions>
</dependency>
<!-- Zookeeper -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.13</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.1</version>
</dependency>
<!-- nacos -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.version}</version>
</dependency>
<!-- easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>

View File

@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.metersphere.api.dubbo;
import io.metersphere.api.dubbo.utils.JsonUtils;
import io.metersphere.api.dubbo.utils.StringUtils;
import java.io.Serializable;
/**
* MethodArgument
*/
public class MethodArgument implements Serializable {
private static final long serialVersionUID = -2567457932227227262L;
private String paramType;
private String paramValue;
public MethodArgument(String paramType, String paramValue) {
setParamType(paramType);
setParamValue(paramValue);
}
public String getParamType() {
return paramType;
}
public void setParamType(String paramType) {
this.paramType = (paramType == null ? null : StringUtils.trimAllWhitespace(paramType));
}
public String getParamValue() {
return paramValue;
}
public void setParamValue(String paramValue) {
this.paramValue = (paramValue == null ? null : StringUtils.trimWhitespace(paramValue));
}
@Override
public String toString() {
return JsonUtils.toJson(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((paramType == null) ? 0 : paramType.hashCode());
result = prime * result + ((paramValue == null) ? 0 : paramValue.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MethodArgument other = (MethodArgument) obj;
if (paramType == null) {
if (other.paramType != null)
return false;
} else if (!paramType.equals(other.paramType))
return false;
if (paramValue == null) {
if (other.paramValue != null)
return false;
} else if (!paramValue.equals(other.paramValue))
return false;
return true;
}
}

View File

@ -0,0 +1,112 @@
package io.metersphere.api.dubbo;
import io.metersphere.api.dubbo.utils.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.ReferenceConfigBase;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
import org.apache.dubbo.registry.RegistryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* ProviderService
*/
public class ProviderService implements Serializable {
private static final Logger log = LoggerFactory.getLogger(ProviderService.class);
private static final long serialVersionUID = -750353929981409079L;
ConcurrentMap<String, Map<String, URL>> providerUrls = null;
private static ConcurrentMap<String, ProviderService> cache = new ConcurrentHashMap<>();
public static ProviderService get(String key) {
ProviderService service = cache.get(key);
if (service == null) {
cache.putIfAbsent(key, new ProviderService());
service = cache.get(key);
}
return service;
}
public Map<String, URL> findByService(String serviceName) {
return providerUrls == null ? null : providerUrls.get(serviceName);
}
public List<String> getProviders(String protocol, String address, String group) throws RuntimeException {
if (protocol.equals("zookeeper") || protocol.equals("nacos") || protocol.equals("redis")) {
return executeRegistry(protocol, address, group);
// } else if (protocol.equals("none")) {
// return executeTelnet();
} else {
throw new RuntimeException("Registry Protocol please use zookeeper or nacos or redis!");
}
}
private List<String> executeTelnet() throws RuntimeException {
throw new RuntimeException();
}
private List<String> executeRegistry(String protocol, String address, String group) throws RuntimeException {
ReferenceConfig reference = new ReferenceConfig();
// set application
reference.setApplication(new ApplicationConfig("DubboSample"));
RegistryConfig registry = null;
switch (protocol) {
case Constants.REGISTRY_ZOOKEEPER:
registry = new RegistryConfig();
registry.setProtocol(Constants.REGISTRY_ZOOKEEPER);
registry.setGroup(group);
registry.setAddress(address);
reference.setRegistry(registry);
break;
case Constants.REGISTRY_NACOS:
registry = new RegistryConfig();
registry.setProtocol(Constants.REGISTRY_NACOS);
registry.setGroup(group);
registry.setAddress(address);
reference.setRegistry(registry);
break;
case Constants.REGISTRY_REDIS:
registry = new RegistryConfig();
registry.setProtocol(Constants.REGISTRY_REDIS);
registry.setGroup(group);
registry.setAddress(address);
reference.setRegistry(registry);
break;
}
reference.setInterface("org.apache.dubbo.registry.RegistryService");
try {
ReferenceConfigCache cache = ReferenceConfigCache.getCache(address + "_" + group, new ReferenceConfigCache.KeyGenerator() {
@Override
public String generateKey(ReferenceConfigBase<?> referenceConfig) {
return referenceConfig.toString();
}
});
RegistryService registryService = (RegistryService) cache.get(reference);
if (registryService == null) {
throw new RuntimeException("Can't get the interface list, please check if the address is wrong!");
}
RegistryServerSync registryServerSync = RegistryServerSync.get(address + "_" + group);
registryService.subscribe(RegistryServerSync.SUBSCRIBE, registryServerSync);
List<String> ret = new ArrayList<String>();
providerUrls = registryServerSync.getRegistryCache().get(com.alibaba.dubbo.common.Constants.PROVIDERS_CATEGORY);
if (providerUrls != null) ret.addAll(providerUrls.keySet());
return ret;
} catch (Exception e) {
log.error("get provider list is error!", e);
throw new RuntimeException("Can't get the interface list, please check if the address is wrong!", e);
}
}
}

View File

@ -0,0 +1,171 @@
package io.metersphere.api.dubbo;
import io.metersphere.api.dubbo.utils.MD5Util;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.constants.RegistryConstants;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.registry.Constants;
import org.apache.dubbo.registry.NotifyListener;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* RegistryServerSync
*/
public class RegistryServerSync implements NotifyListener, Serializable {
private static final long serialVersionUID = -1744756264793278229L;
private static ConcurrentMap<String, RegistryServerSync> cache = new ConcurrentHashMap<>();
public static RegistryServerSync get(String key) {
RegistryServerSync sync = cache.get(key);
if (sync == null) {
cache.putIfAbsent(key, new RegistryServerSync());
sync = cache.get(key);
}
return sync;
}
public static final URL SUBSCRIBE = new URL(Constants.ADMIN_PROTOCOL, NetUtils.getLocalHost(), 0, "",
CommonConstants.INTERFACE_KEY, CommonConstants.ANY_VALUE,
CommonConstants.GROUP_KEY, CommonConstants.ANY_VALUE,
CommonConstants.VERSION_KEY, CommonConstants.ANY_VALUE,
CommonConstants.CLASSIFIER_KEY, CommonConstants.ANY_VALUE,
RegistryConstants.CATEGORY_KEY, RegistryConstants.PROVIDERS_CATEGORY,
// Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY + ","
// + Constants.CONSUMERS_CATEGORY + ","
// + Constants.ROUTERS_CATEGORY + ","
// + Constants.CONFIGURATORS_CATEGORY,
CommonConstants.ENABLED_KEY, CommonConstants.ANY_VALUE,
CommonConstants.CHECK_KEY, String.valueOf(false));
// ConcurrentMap<category, ConcurrentMap<servicename, Map<MD5, URL>>>
private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>>
registryCache = new ConcurrentHashMap<>();
/**
* Make sure ID never changed when the same url notified many times
*/
private final ConcurrentHashMap<String, String> URL_IDS_MAPPER = new ConcurrentHashMap<>();
public RegistryServerSync() {
}
public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
return registryCache;
}
@Override
public void notify(List<URL> urls) {
if (urls == null || urls.isEmpty()) {
return;
}
// Map<category, Map<servicename, Map<Long, URL>>>
final Map<String, Map<String, Map<String, URL>>> categories = new HashMap<>();
String interfaceName = null;
for (URL url : urls) {
String category = url.getParameter(RegistryConstants.CATEGORY_KEY, RegistryConstants.PROVIDERS_CATEGORY);
if (RegistryConstants.EMPTY_PROTOCOL.equalsIgnoreCase(url.getProtocol())) { // NOTE: group and version in empty protocol is *
ConcurrentMap<String, Map<String, URL>> services = registryCache.get(category);
if (services != null) {
String group = url.getParameter(CommonConstants.GROUP_KEY);
String version = url.getParameter(CommonConstants.VERSION_KEY);
// NOTE: group and version in empty protocol is *
if (!CommonConstants.ANY_VALUE.equals(group) && !CommonConstants.ANY_VALUE.equals(version)) {
services.remove(url.getServiceKey());
} else {
for (Map.Entry<String, Map<String, URL>> serviceEntry : services.entrySet()) {
String service = serviceEntry.getKey();
if (this.getInterface(service).equals(url.getServiceInterface())
&& (CommonConstants.ANY_VALUE.equals(group) || StringUtils.isEquals(group, this.getGroup(service)))
&& (CommonConstants.ANY_VALUE.equals(version) || StringUtils.isEquals(version, this.getVersion(service)))) {
services.remove(service);
}
}
}
}
} else {
if (StringUtils.isEmpty(interfaceName)) {
interfaceName = url.getServiceInterface();
}
Map<String, Map<String, URL>> services = categories.get(category);
if (services == null) {
services = new HashMap<>();
categories.put(category, services);
}
String service = url.getServiceKey();
Map<String, URL> ids = services.get(service);
if (ids == null) {
ids = new HashMap<>();
services.put(service, ids);
}
// Make sure we use the same ID for the same URL
if (URL_IDS_MAPPER.containsKey(url.toFullString())) {
ids.put(URL_IDS_MAPPER.get(url.toFullString()), url);
} else {
String md5 = MD5Util.MD5_16bit(url.toFullString());
ids.put(md5, url);
URL_IDS_MAPPER.putIfAbsent(url.toFullString(), md5);
}
}
}
if (categories.size() == 0) {
return;
}
for (Map.Entry<String, Map<String, Map<String, URL>>> categoryEntry : categories.entrySet()) {
String category = categoryEntry.getKey();
ConcurrentMap<String, Map<String, URL>> services = registryCache.get(category);
if (services == null) {
services = new ConcurrentHashMap<String, Map<String, URL>>();
registryCache.put(category, services);
} else {// Fix map can not be cleared when service is unregistered: when a unique group/service:version service is unregistered, but we still have the same services with different version or group, so empty protocols can not be invoked.
Set<String> keys = new HashSet<String>(services.keySet());
for (String key : keys) {
if (this.getInterface(key).equals(interfaceName) && !categoryEntry.getValue().entrySet().contains(key)) {
services.remove(key);
}
}
}
services.putAll(categoryEntry.getValue());
}
}
public String getInterface(String service) {
if (service != null && service.length() > 0) {
int i = service.indexOf('/');
if (i >= 0) {
service = service.substring(i + 1);
}
i = service.lastIndexOf(':');
if (i >= 0) {
service = service.substring(0, i);
}
}
return service;
}
public String getGroup(String service) {
if (service != null && service.length() > 0) {
int i = service.indexOf('/');
if (i >= 0) {
return service.substring(0, i);
}
}
return null;
}
public String getVersion(String service) {
if (service != null && service.length() > 0) {
int i = service.lastIndexOf(':');
if (i >= 0) {
return service.substring(i + 1);
}
}
return null;
}
}

View File

@ -0,0 +1,614 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.metersphere.api.dubbo.utils;
import io.metersphere.api.dubbo.MethodArgument;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.IntegerProperty;
import org.apache.jmeter.testelement.property.StringProperty;
import java.util.ArrayList;
import java.util.List;
/**
* Constants
*/
public class Constants {
//Registry Protocol
public static final String REGISTRY_NONE = "none";
public static final String REGISTRY_ZOOKEEPER = "zookeeper";
public static final String REGISTRY_NACOS = "nacos";
public static final String APOLLO = "apollo";
public static final String REGISTRY_MULTICAST = "multicast";
public static final String REGISTRY_REDIS = "redis";
public static final String REGISTRY_SIMPLE = "simple";
//RPC Protocol
public static final String RPC_PROTOCOL_DUBBO = "dubbo";
public static final String RPC_PROTOCOL_RMI = "rmi";
public static final String RPC_PROTOCOL_HESSIAN = "hessian";
public static final String RPC_PROTOCOL_HTTP = "http";
public static final String RPC_PROTOCOL_WEBSERVICE = "webservice";
public static final String RPC_PROTOCOL_THRIFT = "thrift";
public static final String RPC_PROTOCOL_MEMCACHED = "memcached";
public static final String RPC_PROTOCOL_REDIS = "redis";
public static final String ASYNC = "async";
public static final String SYMBOL = "://";
public static final int INT_DEFAULT = 0;
public static final double DOUBLE_DEFAULT = 0.0d;
public static final boolean BOOLEAN_DEFAULT = false;
public static final char CHAR_DEFAULT = '\u0000';
public static final float FLOAT_DEFAULT = 0.0f;
public static final byte BYTE_DEFAULT = 0;
public static final long LONG_DEFAULT = 0l;
public static final short SHORT_DEFAULT = 0;
public static final int[] INT_ARRAY_DEFAULT = null;
public static final double[] DOUBLE_ARRAY_DEFAULT = null;
public static final boolean[] BOOLEAN_ARRAY_DEFAULT = null;
public static final char[] CHAT_ARRAY_DEFAULT = null;
public static final float[] FLOAT_ARRAY_DEFAULT = null;
public static final byte[] BYTE_ARRAY_DEFAULT = null;
public static final long[] LONG_ARRAY_DEFAULT = null;
public static final short[] SHORT_ARRAY_DEFAULT = null;
public static final String FIELD_DUBBO_REGISTRY_PROTOCOL = "FIELD_DUBBO_REGISTRY_PROTOCOL";
public static final String FIELD_DUBBO_REGISTRY_GROUP = "FIELD_DUBBO_REGISTRY_GROUP";
public static final String FIELD_DUBBO_REGISTRY_USER_NAME = "FIELD_DUBBO_REGISTRY_USER_NAME";
public static final String FIELD_DUBBO_REGISTRY_PASSWORD = "FIELD_DUBBO_REGISTRY_PASSWORD";
public static final String FIELD_DUBBO_REGISTRY_TIMEOUT = "FIELD_DUBBO_REGISTRY_TIMEOUT";
public static final String FIELD_DUBBO_CONFIG_CENTER_PROTOCOL = "FIELD_DUBBO_CONFIG_CENTER_PROTOCOL";
public static final String FIELD_DUBBO_CONFIG_CENTER_GROUP = "FIELD_DUBBO_CONFIG_CENTER_GROUP";
public static final String FIELD_DUBBO_CONFIG_CENTER_NAMESPACE = "FIELD_DUBBO_CONFIG_CENTER_NAMESPACE";
public static final String FIELD_DUBBO_CONFIG_CENTER_USER_NAME = "FIELD_DUBBO_CONFIG_CENTER_USER_NAME";
public static final String FIELD_DUBBO_CONFIG_CENTER_PASSWORD = "FIELD_DUBBO_CONFIG_CENTER_PASSWORD";
public static final String FIELD_DUBBO_CONFIG_CENTER_TIMEOUT = "FIELD_DUBBO_CONFIG_CENTER_TIMEOUT";
public static final String FIELD_DUBBO_CONFIG_CENTER_ADDRESS = "FIELD_DUBBO_CONFIG_CENTER_ADDRESS";
public static final String FIELD_DUBBO_RPC_PROTOCOL = "FIELD_DUBBO_RPC_PROTOCOL";
public static final String FIELD_DUBBO_ADDRESS = "FIELD_DUBBO_ADDRESS";
public static final String FIELD_DUBBO_TIMEOUT = "FIELD_DUBBO_TIMEOUT";
public static final String FIELD_DUBBO_VERSION = "FIELD_DUBBO_VERSION";
public static final String FIELD_DUBBO_RETRIES = "FIELD_DUBBO_RETRIES";
public static final String FIELD_DUBBO_CLUSTER = "FIELD_DUBBO_CLUSTER";
public static final String FIELD_DUBBO_GROUP = "FIELD_DUBBO_GROUP";
public static final String FIELD_DUBBO_CONNECTIONS = "FIELD_DUBBO_CONNECTIONS";
public static final String FIELD_DUBBO_LOADBALANCE = "FIELD_DUBBO_LOADBALANCE";
public static final String FIELD_DUBBO_ASYNC = "FIELD_DUBBO_ASYNC";
public static final String FIELD_DUBBO_INTERFACE = "FIELD_DUBBO_INTERFACE";
public static final String FIELD_DUBBO_METHOD = "FIELD_DUBBO_METHOD";
public static final String FIELD_DUBBO_METHOD_ARGS = "FIELD_DUBBO_METHOD_ARGS";
public static final String FIELD_DUBBO_METHOD_ARGS_SIZE = "FIELD_DUBBO_METHOD_ARGS_SIZE";
public static final String FIELD_DUBBO_ATTACHMENT_ARGS = "FIELD_DUBBO_ATTACHMENT_ARGS";
public static final String FIELD_DUBBO_ATTACHMENT_ARGS_SIZE = "FIELD_DUBBO_ATTACHMENT_ARGS_SIZE";
public static final String DEFAULT_TIMEOUT = "1000";
public static final String DEFAULT_VERSION = "1.0";
public static final String DEFAULT_RETRIES = "0";
public static final String DEFAULT_CLUSTER = "failfast";
public static final String DEFAULT_CONNECTIONS = "100";
//冗余配置元件中的addressprotocolsgroup,用于在sample gui获取配置元件中的默认值
public static String DEFAULT_PANEL_ADDRESS = "";
public static String DEFAULT_PANEL_PROTOCOLS = "";
public static String DEFAULT_PANEL_GROUP = "";
public static final void redundancy(TestElement element) {
DEFAULT_PANEL_ADDRESS = Constants.getAddress(element);
DEFAULT_PANEL_PROTOCOLS = Constants.getRegistryProtocol(element);
DEFAULT_PANEL_GROUP = Constants.getRegistryGroup(element);
}
/**
* get Registry Protocol
*
* @return the protocol
*/
public static final String getRegistryProtocol(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_REGISTRY_PROTOCOL);
}
/**
* set Registry Protocol
*
* @param registryProtocol the protocol to set
*/
public static final void setRegistryProtocol(String registryProtocol, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_REGISTRY_PROTOCOL, StringUtils.trimAllWhitespace(registryProtocol)));
}
/**
* get Registry Group
*
* @return the group
*/
public static final String getRegistryGroup(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_REGISTRY_GROUP);
}
/**
* set Registry Group
*
* @param registryGroup the group to set
*/
public static final void setRegistryGroup(String registryGroup, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_REGISTRY_GROUP, StringUtils.trimAllWhitespace(registryGroup)));
}
/**
* get Registry username
*
* @return the username
*/
public static final String getRegistryUserName(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_REGISTRY_USER_NAME);
}
/**
* set Registry username
*
* @param username the username to set
*/
public static final void setRegistryUserName(String username, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_REGISTRY_USER_NAME, StringUtils.trimAllWhitespace(username)));
}
/**
* get Registry password
*
* @return the password
*/
public static final String getRegistryPassword(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_REGISTRY_PASSWORD);
}
/**
* set Registry password
*
* @param password the password to set
*/
public static final void setRegistryPassword(String password, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_REGISTRY_PASSWORD, StringUtils.trimAllWhitespace(password)));
}
/**
* get Registry timeout
*
* @return the timeout
*/
public static final String getRegistryTimeout(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_REGISTRY_TIMEOUT);
}
/**
* set Registry timeout
*
* @param timeout the group to set
*/
public static final void setRegistryTimeout(String timeout, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_REGISTRY_TIMEOUT, StringUtils.trimAllWhitespace(timeout)));
}
/**
* get ConfigCenter protocol
*
* @return the protocol
*/
public static final String getConfigCenterProtocol(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONFIG_CENTER_PROTOCOL);
}
/**
* set ConfigCenter protocol
*
* @param protocol the protocol to set
*/
public static final void setConfigCenterProtocol(String protocol, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONFIG_CENTER_PROTOCOL, StringUtils.trimAllWhitespace(protocol)));
}
/**
* get ConfigCenter group
*
* @return the group
*/
public static final String getConfigCenterGroup(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONFIG_CENTER_GROUP);
}
/**
* set ConfigCenter group
*
* @param group the group to set
*/
public static final void setConfigCenterGroup(String group, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONFIG_CENTER_GROUP, StringUtils.trimAllWhitespace(group)));
}
/**
* get ConfigCenter namespace
*
* @return the namespace
*/
public static final String getConfigCenterNamespace(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONFIG_CENTER_NAMESPACE);
}
/**
* set ConfigCenter namespace
*
* @param namespace the namespace to set
*/
public static final void setConfigCenterNamespace(String namespace, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONFIG_CENTER_NAMESPACE, StringUtils.trimAllWhitespace(namespace)));
}
/**
* get ConfigCenter username
*
* @return the username
*/
public static final String getConfigCenterUserName(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONFIG_CENTER_USER_NAME);
}
/**
* set ConfigCenter username
*
* @param username the username to set
*/
public static final void setConfigCenterUserName(String username, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONFIG_CENTER_USER_NAME, StringUtils.trimAllWhitespace(username)));
}
/**
* get ConfigCenter password
*
* @return the password
*/
public static final String getConfigCenterPassword(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONFIG_CENTER_PASSWORD);
}
/**
* set ConfigCenter password
*
* @param password the password to set
*/
public static final void setConfigCenterPassword(String password, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONFIG_CENTER_PASSWORD, StringUtils.trimAllWhitespace(password)));
}
/**
* get ConfigCenter address
*
* @return the address
*/
public static final String getConfigCenterAddress(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONFIG_CENTER_ADDRESS);
}
/**
* set ConfigCenter namespace
*
* @param address the address to set
*/
public static final void setConfigCenterAddress(String address, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONFIG_CENTER_ADDRESS, StringUtils.trimAllWhitespace(address)));
}
/**
* get ConfigCenter timeout
*
* @return the timeout
*/
public static final String getConfigCenterTimeout(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONFIG_CENTER_TIMEOUT);
}
/**
* set ConfigCenter namespace
*
* @param timeout the timeout to set
*/
public static final void setConfigCenterTimeout(String timeout, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONFIG_CENTER_TIMEOUT, StringUtils.trimAllWhitespace(timeout)));
}
/**
* get RPC protocol
*
* @return the RPC protocol
*/
public static final String getRpcProtocol(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_RPC_PROTOCOL);
}
/**
* set RPC protocol
*
* @param rpcProtocol the protocol to set
*/
public static final void setRpcProtocol(String rpcProtocol, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_RPC_PROTOCOL, StringUtils.trimAllWhitespace(rpcProtocol)));
}
/**
* get address
*
* @return the address
*/
public static final String getAddress(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_ADDRESS);
}
/**
* set address
*
* @param address the address to set
*/
public static final void setAddress(String address, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_ADDRESS, StringUtils.trimAllWhitespace(address)));
}
/**
* get timeout
*
* @return the timeout
*/
public static final String getTimeout(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_TIMEOUT, DEFAULT_TIMEOUT);
}
/**
* set timeout
*
* @param timeout the timeout to set
*/
public static final void setTimeout(String timeout, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_TIMEOUT, StringUtils.trimAllWhitespace(timeout)));
}
/**
* get version
*
* @return the version
*/
public static final String getVersion(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_VERSION, DEFAULT_VERSION);
}
/**
* set version
*
* @param version the version to set
*/
public static final void setVersion(String version, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_VERSION, StringUtils.trimAllWhitespace(version)));
}
/**
* get retries
*
* @return the retries
*/
public static final String getRetries(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_RETRIES, DEFAULT_RETRIES);
}
/**
* set retries
*
* @param retries the retries to set
*/
public static final void setRetries(String retries, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_RETRIES, StringUtils.trimAllWhitespace(retries)));
}
/**
* get cluster
*
* @return the cluster
*/
public static final String getCluster(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CLUSTER, DEFAULT_CLUSTER);
}
/**
* set cluster
*
* @param cluster the cluster to set
*/
public static final void setCluster(String cluster, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CLUSTER, StringUtils.trimAllWhitespace(cluster)));
}
/**
* get group
*
* @return the group
*/
public static final String getGroup(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_GROUP, null);
}
/**
* set group
*
* @param group the group to set
*/
public static final void setGroup(String group, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_GROUP, StringUtils.trimAllWhitespace(group)));
}
/**
* get connections
*
* @return the group
*/
public static final String getConnections(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_CONNECTIONS, DEFAULT_CONNECTIONS);
}
/**
* set connections
*
* @param connections the connections to set
*/
public static final void setConnections(String connections, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_CONNECTIONS, StringUtils.trimAllWhitespace(connections)));
}
/**
* get loadbalance
*
* @return the loadbalance
*/
public static final String getLoadbalance(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_LOADBALANCE);
}
/**
* set loadbalance
*
* @param loadbalance the loadbalance to set
*/
public static final void setLoadbalance(String loadbalance, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_LOADBALANCE, StringUtils.trimAllWhitespace(loadbalance)));
}
/**
* get async
*
* @return the async
*/
public static final String getAsync(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_ASYNC);
}
/**
* set async
*
* @param async the async to set
*/
public static final void setAsync(String async, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_ASYNC, StringUtils.trimAllWhitespace(async)));
}
/**
* get interfaceName
*
* @return the interfaceName
*/
public static final String getInterface(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_INTERFACE);
}
/**
* set interfaceName
*
* @param interfaceName the interfaceName to set
*/
public static final void setInterfaceName(String interfaceName, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_INTERFACE, StringUtils.trimAllWhitespace(interfaceName)));
}
/**
* get method
*
* @return the method
*/
public static final String getMethod(TestElement element) {
return element.getPropertyAsString(FIELD_DUBBO_METHOD);
}
/**
* set method
*
* @param method the method to set
*/
public static final void setMethod(String method, TestElement element) {
element.setProperty(new StringProperty(FIELD_DUBBO_METHOD, StringUtils.trimAllWhitespace(method)));
}
/**
* get methodArgs
*
* @return the methodArgs
*/
public static final List<MethodArgument> getMethodArgs(TestElement element) {
int paramsSize = element.getPropertyAsInt(FIELD_DUBBO_METHOD_ARGS_SIZE, 0);
List<MethodArgument> list = new ArrayList<MethodArgument>();
for (int i = 1; i <= paramsSize; i++) {
String paramType = element.getPropertyAsString(FIELD_DUBBO_METHOD_ARGS + "_PARAM_TYPE" + i);
String paramValue = element.getPropertyAsString(FIELD_DUBBO_METHOD_ARGS + "_PARAM_VALUE" + i);
MethodArgument args = new MethodArgument(paramType, paramValue);
list.add(args);
}
return list;
}
/**
* set methodArgs
*
* @param methodArgs the methodArgs to set
*/
public static final void setMethodArgs(List<MethodArgument> methodArgs, TestElement element) {
int size = methodArgs == null ? 0 : methodArgs.size();
element.setProperty(new IntegerProperty(FIELD_DUBBO_METHOD_ARGS_SIZE, size));
if (size > 0) {
for (int i = 1; i <= methodArgs.size(); i++) {
element.setProperty(new StringProperty(FIELD_DUBBO_METHOD_ARGS + "_PARAM_TYPE" + i, methodArgs.get(i - 1).getParamType()));
element.setProperty(new StringProperty(FIELD_DUBBO_METHOD_ARGS + "_PARAM_VALUE" + i, methodArgs.get(i - 1).getParamValue()));
}
}
}
/**
* get attachmentArgs
*
* @return the attachmentArgs
*/
public static final List<MethodArgument> getAttachmentArgs(TestElement element) {
int paramsSize = element.getPropertyAsInt(FIELD_DUBBO_ATTACHMENT_ARGS_SIZE, 0);
List<MethodArgument> list = new ArrayList<MethodArgument>();
for (int i = 1; i <= paramsSize; i++) {
String paramType = element.getPropertyAsString(FIELD_DUBBO_ATTACHMENT_ARGS + "_KEY" + i);
String paramValue = element.getPropertyAsString(FIELD_DUBBO_ATTACHMENT_ARGS + "_VALUE" + i);
MethodArgument args = new MethodArgument(paramType, paramValue);
list.add(args);
}
return list;
}
/**
* set attachmentArgs
*
* @param methodArgs the attachmentArgs to set
*/
public static final void setAttachmentArgs(List<MethodArgument> methodArgs, TestElement element) {
int size = methodArgs == null ? 0 : methodArgs.size();
element.setProperty(new IntegerProperty(FIELD_DUBBO_ATTACHMENT_ARGS_SIZE, size));
if (size > 0) {
for (int i = 1; i <= methodArgs.size(); i++) {
element.setProperty(new StringProperty(FIELD_DUBBO_ATTACHMENT_ARGS + "_KEY" + i, methodArgs.get(i - 1).getParamType()));
element.setProperty(new StringProperty(FIELD_DUBBO_ATTACHMENT_ARGS + "_VALUE" + i, methodArgs.get(i - 1).getParamValue()));
}
}
}
}

View File

@ -0,0 +1,52 @@
package io.metersphere.api.dubbo.utils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
/**
* JsonUtils
*/
public class JsonUtils {
private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
private static final Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.setPrettyPrinting()
.disableHtmlEscaping()
.serializeNulls()
.create();
public static String toJson(Object obj) {
return gson.toJson(obj);
}
public static String toJson(Object obj, Type type) {
return gson.toJson(obj, type);
}
public static <T> T formJson(String json, Class<T> classOfT) {
try {
return gson.fromJson(json, classOfT);
} catch (JsonSyntaxException e) {
logger.error("json to class[" + classOfT.getName() + "] is error!",
e);
}
return null;
}
public static <T> T formJson(String json, Type type) {
try {
return gson.fromJson(json, type);
} catch (JsonSyntaxException e) {
logger.error("json to class[" + type.getClass().getName()
+ "] is error!", e);
}
return null;
}
}

View File

@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.metersphere.api.dubbo.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* MD5Util
*/
public class MD5Util {
private static MessageDigest md;
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
static {
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public static String MD5_16bit(String input) {
String hash = MD5_32bit(input);
if (hash == null) {
return null;
}
return hash.substring(8, 24);
}
public static String MD5_32bit(String input) {
if (input == null || input.length() == 0) {
return null;
}
md.update(input.getBytes());
byte[] digest = md.digest();
String hash = convertToString(digest);
return hash;
}
private static String convertToString(byte[] data) {
StringBuilder r = new StringBuilder(data.length * 2);
for (byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
}
}

View File

@ -0,0 +1,69 @@
package io.metersphere.api.dubbo.utils;
/**
* StringUtils
*/
public class StringUtils {
public static boolean hasLength(String str) {
return str != null && !str.isEmpty();
}
public static String trimAllWhitespace(String str) {
if (!hasLength(str)) {
return str;
} else {
int len = str.length();
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < len; ++i) {
char c = str.charAt(i);
if (!Character.isWhitespace(c)) {
sb.append(c);
}
}
return sb.toString();
}
}
public static String trimWhitespace(String str) {
if (!hasLength(str)) {
return str;
} else {
StringBuilder sb = new StringBuilder(str);
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
sb.deleteCharAt(0);
}
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}
public static boolean isBlank(CharSequence cs) {
int strLen;
if (cs != null && (strLen = cs.length()) != 0) {
for (int i = 0; i < strLen; ++i) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
} else {
return true;
}
}
public static boolean isBlank1(String paramValue) {
if (isBlank(paramValue) || "null".equals(paramValue.toLowerCase())) {
return true;
}
return false;
}
}

View File

@ -118,10 +118,14 @@ public class APITestService {
public APITestResult get(String id) {
APITestResult apiTest = new APITestResult();
BeanUtils.copyBean(apiTest, apiTestMapper.selectByPrimaryKey(id));
Schedule schedule = scheduleService.getScheduleByResource(id, ScheduleGroup.API_TEST.name());
apiTest.setSchedule(schedule);
return apiTest;
ApiTest test = apiTestMapper.selectByPrimaryKey(id);
if (test != null) {
BeanUtils.copyBean(apiTest, test);
Schedule schedule = scheduleService.getScheduleByResource(id, ScheduleGroup.API_TEST.name());
apiTest.setSchedule(schedule);
return apiTest;
}
return null;
}
public ApiTest getApiTestByTestId(String testId) {

View File

@ -18,6 +18,8 @@ public interface ExtTestPlanTestCaseMapper {
List<TestPlanCaseDTO> listByNode(@Param("request") QueryTestPlanCaseRequest request);
List<TestPlanCaseDTO> listByNodes(@Param("request") QueryTestPlanCaseRequest request);
List<String> findRelateTestPlanId(@Param("userId") String userId, @Param("workspaceId") String workspaceId);
List<TestPlanCaseDTO> getRecentTestedTestCase(@Param("request") QueryTestPlanCaseRequest request);

View File

@ -2,7 +2,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.ExtTestPlanTestCaseMapper">
<select id="getReportMetric" parameterType="java.lang.String" resultType="io.metersphere.track.dto.TestCaseReportStatusResultDTO">
<select id="getReportMetric" parameterType="java.lang.String"
resultType="io.metersphere.track.dto.TestCaseReportStatusResultDTO">
select count(t1.id) as `count`, t1.status
from test_plan_test_case t1
inner join test_case t2
@ -45,6 +46,9 @@
<if test="request.planId != null">
and test_plan_test_case.plan_id = #{request.planId}
</if>
<if test="request.method != null">
and test_case.method = #{request.method}
</if>
<if test="request.filters != null and request.filters.size() > 0">
<foreach collection="request.filters.entrySet()" index="key" item="values">
<if test="values != null and values.size() > 0">
@ -84,6 +88,27 @@
</where>
</select>
<select id="listByNodes" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
select test_plan_test_case.*, test_case.*
from test_plan_test_case
inner join test_case on test_plan_test_case.case_id = test_case.id
<where>
<if test="request.planId != null">
and test_plan_test_case.plan_id = #{request.planId}
</if>
<if test="request.method != null">
and test_case.method = #{request.method}
</if>
<if test="request.nodePaths != null and request.nodePaths.size() > 0">
and
<foreach collection="request.nodePaths" item="nodePaths" separator="or" index="index">
test_case.node_path like concat('%',#{nodePaths},'%')
</foreach>
</if>
</where>
</select>
<select id="findRelateTestPlanId" resultType="java.lang.String">

View File

@ -1,7 +1,5 @@
package io.metersphere.performance.engine;
import java.util.Map;
public interface Engine {
Long getStartTime();
@ -10,6 +8,4 @@ public interface Engine {
void start();
void stop();
Map<String, String> log();
}

View File

@ -15,9 +15,7 @@ import io.metersphere.performance.engine.EngineFactory;
import io.metersphere.performance.engine.docker.request.TestRequest;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class DockerTestEngine extends AbstractEngine {
@ -110,25 +108,9 @@ public class DockerTestEngine extends AbstractEngine {
try {
restTemplateWithTimeOut.getForObject(uri, String.class);
} catch (Exception e) {
LogUtil.error("stop load test fail... " + testId);
MSException.throwException(Translator.get("delete_fail"));
LogUtil.error("stop load test fail... " + testId, e);
MSException.throwException(Translator.get("container_delete_fail") + ", Error: " + e.getMessage());
}
});
}
@Override
public Map<String, String> log() {
String testId = loadTest.getId();
Map<String, String> logs = new HashMap<>();
this.resourceList.forEach(r -> {
NodeDTO node = JSON.parseObject(r.getConfiguration(), NodeDTO.class);
String ip = node.getIp();
Integer port = node.getPort();
String uri = String.format(BASE_URL + "/jmeter/container/log/" + testId, ip, port);
String log = restTemplate.getForObject(uri, String.class);
logs.put(node.getIp(), log);
});
return logs;
}
}

View File

@ -75,8 +75,6 @@ public class SystemParameterService {
javaMailSender.setUsername(hashMap.get(ParamConstants.MAIL.ACCOUNT.getKey()));
javaMailSender.setPassword(hashMap.get(ParamConstants.MAIL.PASSWORD.getKey()));
Properties props = new Properties();
props.put("mail.smtp.timeout", "5000");
props.put("mail.smtp.connectiontimeout", "5000");
props.put("mail.smtp.auth", "true");
if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.SSL.getKey()))) {
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
@ -84,6 +82,8 @@ public class SystemParameterService {
if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.TLS.getKey()))) {
props.put("mail.smtp.starttls.enable", "true");
}
props.put("mail.smtp.timeout", "30000");
props.put("mail.smtp.connectiontimeout", "5000");
javaMailSender.setJavaMailProperties(props);
try {
javaMailSender.testConnection();

View File

@ -33,9 +33,16 @@ public class TestPlanTestCaseController {
return PageUtils.setPageInfo(page, testPlanTestCaseService.list(request));
}
/*jenkins测试计划下的测试用例*/
@GetMapping("/list/{planId}")
public List<TestPlanCaseDTO> getTestPlanCaseByPlanId(@PathVariable String planId) {
QueryTestPlanCaseRequest request = new QueryTestPlanCaseRequest();
request.setPlanId(planId);
request.setMethod("auto");
return testPlanTestCaseService.list(request);
}
@GetMapping("/list/node/{planId}/{nodePaths}")
public List<TestPlanCaseDTO> getTestPlanCases(@PathVariable String planId, @PathVariable String nodePaths) {
public List<TestPlanCaseDTO> getTestPlanCasesByNodePath(@PathVariable String planId, @PathVariable String nodePaths) {
String nodePath = nodePaths.replace("f", "/");
String[] array = nodePath.split(",");
List<String> list = Arrays.asList(array);
@ -46,6 +53,18 @@ public class TestPlanTestCaseController {
return testPlanTestCaseService.listByNode(request);
}
@GetMapping("/list/node/all/{planId}/{nodePaths}")
public List<TestPlanCaseDTO> getTestPlanCasesByNodePaths(@PathVariable String planId, @PathVariable String nodePaths) {
String nodePath = nodePaths.replace("f", "");
String[] array = nodePath.split(",");
List<String> list = Arrays.asList(array);
QueryTestPlanCaseRequest request = new QueryTestPlanCaseRequest();
request.setPlanId(planId);
request.setNodePaths(list);
request.setMethod("auto");
return testPlanTestCaseService.listByNodes(request);
}
@GetMapping("/get/{caseId}")
public TestPlanCaseDTO getTestPlanCases(@PathVariable String caseId) {
return testPlanTestCaseService.get(caseId);

View File

@ -60,6 +60,11 @@ public class TestPlanTestCaseService {
return list;
}
public List<TestPlanCaseDTO> listByNodes(QueryTestPlanCaseRequest request) {
List<TestPlanCaseDTO> list = extTestPlanTestCaseMapper.listByNodes(request);
return list;
}
public void editTestCase(TestPlanTestCaseWithBLOBs testPlanTestCase) {
if (StringUtils.equals(TestPlanTestCaseStatus.Prepare.name(), testPlanTestCase.getStatus())) {
testPlanTestCase.setStatus(TestPlanTestCaseStatus.Underway.name());

View File

@ -46,6 +46,7 @@ max_thread_insufficient=The number of concurrent users exceeds
related_case_del_fail_prefix=Connected to
related_case_del_fail_suffix=TestCase, please disassociate first
jmx_content_valid=JMX content is invalid
container_delete_fail=The container failed to stop, please try again
#workspace
workspace_name_is_null=Workspace name cannot be null
workspace_name_already_exists=The workspace name already exists

View File

@ -46,6 +46,7 @@ max_thread_insufficient=并发用户数超额
related_case_del_fail_prefix=已关联到
related_case_del_fail_suffix=测试用例,请先解除关联
jmx_content_valid=JMX 内容无效,请检查
container_delete_fail=容器停止失败,请重试
#workspace
workspace_name_is_null=工作空间名不能为空
workspace_name_already_exists=工作空间名已存在

View File

@ -46,6 +46,7 @@ max_thread_insufficient=並發用戶數超額
related_case_del_fail_prefix=已關聯到
related_case_del_fail_suffix=測試用例,請先解除關聯
jmx_content_valid=JMX 內容無效,請檢查
container_delete_fail=容器停止失敗,請重試
#workspace
workspace_name_is_null=工作空間名不能為空
workspace_name_already_exists=工作空間名已存在

View File

@ -400,12 +400,12 @@ class JMXRequest {
this.pathname = decodeURIComponent(url.pathname);
this.port = url.port;
this.protocol = url.protocol.split(":")[0];
this.pathname = this.getPostQueryParameters(request, this.pathname);
this.pathname = this.getPostQueryParameters(request, this.pathname);
} else {
this.environment = request.environment;
this.port = request.environment.port;
this.path = decodeURIComponent(request.path);
this.path = this.getPostQueryParameters(request, this.path);
this.path = this.getPostQueryParameters(request, this.path);
}
}
}
@ -485,22 +485,26 @@ class JMXGenerator {
})
}
addScenarioVariables(threadGroup, scenario) {
let scenarioVariableKeys = new Set();
scenario.variables.forEach(item => {
scenarioVariableKeys.add(item.name);
addEnvironments(environments, target) {
let keys = new Set();
target.forEach(item => {
keys.add(item.name);
});
let envArray = environments;
if (!(envArray instanceof Array)) {
envArray = JSON.parse(environments);
envArray.forEach(item => {
if (item.name && !keys.has(item.name)) {
target.push(new KeyValue(item.name, item.value));
}
})
}
}
addScenarioVariables(threadGroup, scenario) {
let environment = scenario.environment;
if (environment) {
let envVariables = environment.variables;
if (!(envVariables instanceof Array)) {
envVariables = JSON.parse(environment.variables);
envVariables.forEach(item => {
if (item.name && !scenarioVariableKeys.has(item.name)) {
scenario.variables.push(new KeyValue(item.name, item.value));
}
})
}
this.addEnvironments(environment.variables, scenario.variables)
}
let args = this.filterKV(scenario.variables);
if (args.length > 0) {
@ -510,21 +514,9 @@ class JMXGenerator {
}
addScenarioHeaders(threadGroup, scenario) {
let scenarioHeaderKeys = new Set();
scenario.headers.forEach(item => {
scenarioHeaderKeys.add(item.name);
});
let environment = scenario.environment;
if (environment) {
let envHeaders = environment.headers;
if (!(envHeaders instanceof Array)) {
envHeaders = JSON.parse(environment.headers);
envHeaders.forEach(item => {
if (item.name && !scenarioHeaderKeys.has(item.name)) {
scenario.headers.push(new KeyValue(item.name, item.value));
}
})
}
this.addEnvironments(environment.headers, scenario.headers)
}
let headers = this.filterKV(scenario.headers);
if (headers.length > 0) {

View File

@ -72,9 +72,13 @@
reset() {
let source = this.condition.components;
this.config.components.forEach((component, index) => {
let operator = source[index].operator.value;
component.operator.value = operator === undefined ? component.operator.options[0].value : operator;
component.value = source[index].value;
if (component.operator.value !== undefined) {
let operator = source[index].operator.value;
component.operator.value = operator === undefined ? component.operator.options[0].value : operator;
}
if (component.value !== undefined) {
component.value = source[index].value;
}
})
},
open() {

View File

@ -215,8 +215,8 @@ export const MODULE = {
name: 'MsTableSearchInput',
label: "test_track.case.module",
operator: {
value: OPERATORS.LIKE.value, // 如果未设置value初始值则value初始值为options[0]
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE] // 运算符候选项
value: OPERATORS.LIKE.value,
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE]
},
}

View File

@ -57,7 +57,8 @@
</el-dialog>
<!--Change personal password-->
<el-dialog :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="35%" :before-close='closeDialog' left >
<el-dialog :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="35%"
:destroy-on-close="true" @close="handleClose" left>
<el-form :model="ruleForm" :rules="rules" ref="editPasswordForm" label-width="120px" class="demo-ruleForm">
<el-form-item :label="$t('member.old_password')" prop="password" style="margin-bottom: 29px">
<el-input v-model="ruleForm.password" autocomplete="off" show-password/>
@ -68,7 +69,7 @@
</el-form>
<span slot="footer" class="dialog-footer">
<ms-dialog-footer
@cancel="cancel()"
@cancel="editPasswordVisible = false"
@confirm="updatePassword('editPasswordForm')"/>
</span>
</el-dialog>

View File

@ -267,7 +267,8 @@
</template>
</el-dialog>
<!--Changing user password in system settings-->
<el-dialog :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="30%" left>
<el-dialog :title="$t('member.edit_password')" :visible.sync="editPasswordVisible" width="30%"
:destroy-on-close="true" @close="handleClose" left>
<el-form :model="ruleForm" label-position="right" label-width="120px" size="small" :rules="rule"
ref="editPasswordForm" class="demo-ruleForm">
<el-form-item :label="$t('member.new_password')" prop="newpassword">

View File

@ -10,9 +10,9 @@
<node-breadcrumb class="table-title" :nodes="selectParentNodes" @refresh="refresh"/>
</template>
<template v-slot:button>
<ms-table-button :is-tester-permission="true" icon="el-icon-upload2"
:content="$t('test_track.case.import.import')" @click="importTestCase"/>
<ms-table-button :is-tester-permission="true" icon="el-icon-download"
:content="$t('test_track.case.import.import')" @click="importTestCase"/>
<ms-table-button :is-tester-permission="true" icon="el-icon-upload2"
:content="$t('test_track.case.export.export')" @click="handleBatch('export')"/>
<ms-table-button :is-tester-permission="true" icon="el-icon-right" :content="$t('test_track.case.move')"
@click="handleBatch('move')"/>

View File

@ -282,6 +282,21 @@
+ this.$t('test_track.length_less_than') + '300');
return;
}
if (this.testCase.method != 'auto') {
if (!result.actualResult) {
this.$warning(this.testCase.steptResults[i].desc + this.$t('test_track.actual_result')
);
return;
}
if (!result.executeResult) {
this.$warning(this.testCase.steptResults[i].desc + this.$t('test_track.execution_result')
);
return;
}
}
param.results.push(result);
}
@ -380,7 +395,13 @@
getRelatedTest() {
if (this.testCase.method == 'auto' && this.testCase.testId) {
this.$get('/' + this.testCase.type + '/get/' + this.testCase.testId, response => {
this.test = response.data;
let data = response.data;
if (data) {
this.test = data;
} else {
this.test = {};
this.$warning(this.$t("test_track.case.relate_test_not_find"));
}
});
}
},

View File

@ -70,6 +70,8 @@
});
this.getProject(item.projectId);
this.$refs.config.reset();
} else {
this.test = new Test();
}
});
},

View File

@ -93,8 +93,12 @@
getTest() {
if (this.id) {
this.result = this.$get('/performance/get/' + this.id, response => {
this.test = response.data;
this.getProject(this.test.projectId);
if (response.data) {
this.test = response.data;
this.getProject(this.test.projectId);
} else {
this.test = {};
}
});
}
},

View File

@ -464,6 +464,8 @@ export default {
recent_plan: "Recent plan",
recent_case: "Recent case",
pass_rate: "Pass rate",
execution_result: ": Please select the execution result",
actual_result: ": The actual result is empty",
case: {
test_case: "Case",
move: "Move case",
@ -500,6 +502,7 @@ export default {
please_create_project: "No project available, please create the project first",
create_module_first: "Please create module first",
relate_test: "Relate test",
relate_test_not_find: 'The associated test does not exist, please check the test case',
import: {
import: "Import test case",
case_import: "Import test case",

View File

@ -463,6 +463,9 @@ export default {
recent_plan: "最近的计划",
recent_case: "最近的用例",
pass_rate: "通过率",
execution_result: ": 请选择执行结果",
actual_result: ": 实际结果为空",
case: {
test_case: "测试用例",
move: "移动用例",
@ -499,6 +502,7 @@ export default {
please_create_project: "暂无项目,请先创建项目",
create_module_first: "请先新建模块",
relate_test: "关联测试",
relate_test_not_find: '关联的测试不存在,请检查用例',
import: {
import: "导入用例",
case_import: "导入测试用例",

View File

@ -463,6 +463,8 @@ export default {
recent_plan: "最近的計劃",
recent_case: "最近的用例",
pass_rate: "通過率",
execution_result: ": 請選擇執行結果",
actual_result: ": 實際結果為空",
case: {
test_case: "測試用例",
move: "移動用例",
@ -499,6 +501,7 @@ export default {
please_create_project: "暫無項目,請先創建項目",
create_module_first: "請先新建模塊",
relate_test: "關聯測試",
relate_test_not_find: '關聯的測試不存在,請檢查用例',
import: {
import: "導入用例",
case_import: "導入測試用例",