├── settings.gradle ├── src └── main │ ├── groovy │ └── com │ │ └── okay │ │ └── family │ │ ├── service │ │ ├── ILiveUpdateService.java │ │ ├── impl │ │ │ ├── LiveUpdateServiceImpl.java │ │ │ └── PubDataServiceImpl.java │ │ ├── ICommonService.java │ │ ├── IPubDataService.java │ │ ├── ITestUserService.java │ │ ├── ITestCaseService.java │ │ └── ICaseCollectionService.java │ │ ├── fun │ │ ├── base │ │ │ ├── interfaces │ │ │ │ ├── ReturnCode.java │ │ │ │ ├── MarkRequest.java │ │ │ │ ├── MarkThread.java │ │ │ │ └── IMessage.java │ │ │ ├── exception │ │ │ │ ├── LoginException.java │ │ │ │ ├── ParamException.java │ │ │ │ ├── FailException.java │ │ │ │ ├── RequestException.java │ │ │ │ └── VerifyException.java │ │ │ ├── bean │ │ │ │ ├── BeanUtil.groovy │ │ │ │ ├── PerformanceResultBean.groovy │ │ │ │ ├── AbstractBean.groovy │ │ │ │ ├── RecordBean.groovy │ │ │ │ └── Result.groovy │ │ │ └── constaint │ │ │ │ ├── FixedQpsThread.java │ │ │ │ ├── ThreadBase.java │ │ │ │ └── ThreadLimitTimeCount.java │ │ ├── config │ │ │ ├── SysInit.java │ │ │ └── RequestType.java │ │ ├── utils │ │ │ ├── CountTool.groovy │ │ │ ├── HeapDumper.java │ │ │ ├── FileUtil.groovy │ │ │ ├── Join.java │ │ │ ├── Regex.java │ │ │ └── RString.groovy │ │ └── frame │ │ │ ├── thead │ │ │ ├── ParamMark.java │ │ │ ├── RequestThreadTime.java │ │ │ ├── HeaderMark.java │ │ │ └── RequestThreadTimes.java │ │ │ ├── httpclient │ │ │ └── GCThread.java │ │ │ ├── execute │ │ │ └── ThreadPoolUtil.groovy │ │ │ ├── Save.java │ │ │ └── socket │ │ │ └── SocketClient.java │ │ ├── common │ │ ├── basedata │ │ │ ├── NodeLock.java │ │ │ ├── FamilyConstant.java │ │ │ ├── OkayMethod.groovy │ │ │ ├── UserLock.java │ │ │ ├── ServerHost.groovy │ │ │ └── OkayConstant.java │ │ ├── bean │ │ │ ├── common │ │ │ │ ├── ProjectBean.groovy │ │ │ │ ├── SimpleBean.groovy │ │ │ │ └── DelBean.groovy │ │ │ ├── casecollect │ │ │ │ ├── response │ │ │ │ │ ├── ListCaseBean.groovy │ │ │ │ │ ├── ListCaseRunRecord.groovy │ │ │ │ │ ├── CollectionRunSimpleResutl.groovy │ │ │ │ │ ├── ListCollectionBean.groovy │ │ │ │ │ ├── CollectionCaseInfoBean.groovy │ │ │ │ │ └── CollectionRunResultDetailBean.groovy │ │ │ │ └── request │ │ │ │ │ ├── DelCollectionBean.groovy │ │ │ │ │ ├── CaseCollectionEditRecord.groovy │ │ │ │ │ ├── DelCaseCollectionRelationBean.groovy │ │ │ │ │ ├── CollectionEditBean.groovy │ │ │ │ │ ├── SearchCollectionNoPageBean.groovy │ │ │ │ │ ├── CollectionRunResultRecord.groovy │ │ │ │ │ ├── RunCollectionBean.groovy │ │ │ │ │ ├── AddCollectionBean.groovy │ │ │ │ │ └── SearchCollectionBean.groovy │ │ │ ├── pubdata │ │ │ │ ├── response │ │ │ │ │ └── PubDataBean.groovy │ │ │ │ ├── PubDataDetailBean.groovy │ │ │ │ └── request │ │ │ │ │ ├── SavePubDataBean.groovy │ │ │ │ │ └── EditPubBean.groovy │ │ │ ├── testcase │ │ │ │ ├── CaseVerifyBean.groovy │ │ │ │ ├── response │ │ │ │ │ ├── CaseEditRetrunRecord.groovy │ │ │ │ │ ├── ListCaseRunResultBean.groovy │ │ │ │ │ ├── TestCaseListBean.groovy │ │ │ │ │ ├── CaseRunDetailBean.groovy │ │ │ │ │ ├── CaseDetailBean.groovy │ │ │ │ │ └── TestCaseAttributeBean.groovy │ │ │ │ ├── request │ │ │ │ │ ├── CaseEditRecord.groovy │ │ │ │ │ ├── CaseEditRecordQueryBean.groovy │ │ │ │ │ ├── CaseSearchNoPageBean.groovy │ │ │ │ │ ├── EditCaseAttributeBean.groovy │ │ │ │ │ └── CaseSearchBean.groovy │ │ │ │ └── CaseRunRecord.groovy │ │ │ ├── testuser │ │ │ │ ├── response │ │ │ │ │ └── TestUserBean.groovy │ │ │ │ ├── request │ │ │ │ │ ├── SearchUserBean.groovy │ │ │ │ │ └── EditUserBean.groovy │ │ │ │ └── TestUserCheckBean.groovy │ │ │ └── RequestSaveBean.groovy │ │ ├── WebSocketConfig.java │ │ ├── code │ │ │ ├── DataBaseCode.groovy │ │ │ ├── PubDataCode.groovy │ │ │ ├── TestUserCode.groovy │ │ │ ├── CollectionCode.groovy │ │ │ ├── TestCaseCode.groovy │ │ │ └── CommonCode.groovy │ │ ├── ScheduledConfig.java │ │ ├── enums │ │ │ ├── PubStatus.groovy │ │ │ ├── DelStatus.groovy │ │ │ ├── CaseAvailableStatus.groovy │ │ │ ├── UserState.groovy │ │ │ ├── CaseEditType.groovy │ │ │ ├── CollectionStatus.groovy │ │ │ ├── RunResult.groovy │ │ │ ├── CaseLevel.groovy │ │ │ ├── Identity.groovy │ │ │ ├── RequestType.groovy │ │ │ └── CollectionEditType.groovy │ │ ├── exception │ │ │ ├── CaseException.java │ │ │ ├── CommonException.java │ │ │ ├── UserStatusException.java │ │ │ └── CaseCollecionException.java │ │ ├── threadpool │ │ │ ├── OkayThreadPool.java │ │ │ ├── CaseParamaThread.java │ │ │ └── CaseRunThread.java │ │ ├── wapper │ │ │ ├── LogConfig.java │ │ │ ├── CommonInterceptor.java │ │ │ ├── ResponseWrapper.java │ │ │ ├── WrappingFilter.java │ │ │ └── RequestWrapper.java │ │ ├── Task.groovy │ │ ├── StartRun.java │ │ └── typehandler │ │ │ ├── JsonArrayHandler.java │ │ │ ├── JsonHandler.java │ │ │ ├── ListIntegerHandler.java │ │ │ ├── ListPubDetailHandler.java │ │ │ ├── ListCaseVerifyBeanHandler.java │ │ │ └── ResultArrayHandler.java │ │ ├── utils │ │ ├── xml │ │ │ ├── NodeInfo.groovy │ │ │ ├── Attr.groovy │ │ │ ├── XMLUtil2.groovy │ │ │ └── XMLUtil.groovy │ │ ├── RequestSave.java │ │ ├── HandleCaseParamsUtil.groovy │ │ ├── VerifyResponseUtil.groovy │ │ └── RunCaseUtil.java │ │ ├── mapper │ │ ├── CommonMapper.java │ │ ├── PubDataMapper.java │ │ ├── TestUserMapper.java │ │ ├── TestCaseMapper.java │ │ └── CaseCollectionMapper.java │ │ ├── FamilyApplication.java │ │ ├── middle │ │ └── common │ │ │ ├── Common.java │ │ │ └── CasCredential.groovy │ │ └── controller │ │ ├── LiveUpdateController.java │ │ ├── TestUserController.java │ │ ├── PubDataController.java │ │ └── CommonDataController.java │ └── resources │ ├── mapper │ ├── CommonMapper.xml │ └── PubDataMapper.xml │ ├── app.sh │ └── logback.xml ├── readme.markdown └── gradlew.bat /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'family-qa' 2 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/ILiveUpdateService.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service; 2 | 3 | public interface ILiveUpdateService { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/interfaces/ReturnCode.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.interfaces; 2 | 3 | public interface ReturnCode { 4 | 5 | int getCode(); 6 | 7 | String getDesc(); 8 | 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/basedata/NodeLock.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.basedata; 2 | 3 | public class NodeLock { 4 | 5 | private static final int USER_LOCK_PREFIX = 1_000_000; 6 | 7 | public static int getUserLock(int uid) { 8 | return USER_LOCK_PREFIX + uid; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/common/ProjectBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.common 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | class ProjectBean extends AbstractBean{ 6 | 7 | private static final long serialVersionUID = 168461652315615; 8 | 9 | Integer id 10 | 11 | String name 12 | 13 | String version 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/xml/NodeInfo.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils.xml 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | 6 | /** 7 | * 节点信息 8 | */ 9 | class NodeInfo extends AbstractBean { 10 | 11 | private static final long serialVersionUID = 568896512159847L 12 | 13 | List attrs 14 | 15 | List children 16 | 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/response/ListCaseBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例列表展示 7 | */ 8 | class ListCaseBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = 69384703278; 11 | 12 | 13 | Integer id 14 | 15 | Integer isEdit 16 | 17 | String name 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/interfaces/MarkRequest.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.interfaces; 2 | 3 | import org.apache.http.client.methods.HttpRequestBase; 4 | 5 | /** 6 | * 专门用来标记HTTP请求的接口 7 | */ 8 | public interface MarkRequest extends MarkThread { 9 | 10 | /** 11 | * 标记请求对象 12 | * 13 | * @param requestBase 14 | * @return 15 | */ 16 | public String mark(HttpRequestBase requestBase); 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/interfaces/MarkThread.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.interfaces; 2 | 3 | 4 | import com.okay.family.fun.base.constaint.ThreadBase; 5 | 6 | /** 7 | * 用来标记thread,为了记录超时的请求 8 | */ 9 | public interface MarkThread { 10 | 11 | /** 12 | * 标记线程任务 13 | * 14 | * @param threadBase 15 | * @return 16 | */ 17 | public String mark(ThreadBase threadBase); 18 | 19 | public MarkThread clone(); 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/impl/LiveUpdateServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service.impl; 2 | 3 | import com.okay.family.service.ILiveUpdateService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class LiveUpdateServiceImpl implements ILiveUpdateService { 10 | 11 | private static Logger logger = LoggerFactory.getLogger(LiveUpdateServiceImpl.class); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/pubdata/response/PubDataBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.pubdata.response 2 | 3 | import com.okay.family.common.bean.pubdata.PubDataDetailBean 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | 6 | class PubDataBean extends AbstractBean { 7 | 8 | private static final long serialVersionUID = 8754205931721071606L; 9 | 10 | Integer id 11 | 12 | List children 13 | 14 | String name 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/xml/Attr.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils.xml 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | 6 | /** 7 | * 节点属性信息 8 | */ 9 | class Attr extends AbstractBean { 10 | 11 | private static final long serialVersionUID = -35484487563215649L 12 | 13 | String name 14 | 15 | String value 16 | 17 | public Attr(String name, String value) { 18 | this.name = name 19 | this.value = value 20 | } 21 | 22 | 23 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/ICommonService.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service; 2 | 3 | import com.okay.family.common.bean.RequestSaveBean; 4 | 5 | import java.util.Map; 6 | 7 | public interface ICommonService { 8 | 9 | Map findAllHost(); 10 | 11 | void saveRequest(RequestSaveBean bean); 12 | 13 | String getHost(int envId, int service_id); 14 | 15 | int lock(long lock); 16 | 17 | int unlock(long lock); 18 | 19 | void clearLock(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/response/ListCaseRunRecord.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例运行结果列表展示 7 | */ 8 | class ListCaseRunRecord extends AbstractBean{ 9 | 10 | private static final long serialVersionUID = 3884914894898; 11 | 12 | Integer id 13 | 14 | String name 15 | 16 | String result 17 | 18 | String serviceName 19 | 20 | String url 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/CaseVerifyBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase 2 | 3 | 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import com.okay.family.fun.config.Constant 6 | /** 7 | * 测试期望 8 | */ 9 | class CaseVerifyBean extends AbstractBean { 10 | 11 | private static final long serialVersionUID = -1595942567071153982L; 12 | 13 | String text 14 | 15 | String value 16 | 17 | String des = Constant.EMPTY 18 | 19 | String result 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/response/CaseEditRetrunRecord.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例编辑记录 7 | */ 8 | class CaseEditRetrunRecord extends AbstractBean { 9 | 10 | private static final long serialVersionUID = -349027423875; 11 | 12 | Integer id 13 | 14 | Integer caseId 15 | 16 | String people 17 | 18 | String time 19 | 20 | String handleType 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/response/ListCaseRunResultBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例运行记录列表 7 | */ 8 | class ListCaseRunResultBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = 21209389021819; 11 | 12 | Integer id 13 | 14 | String name 15 | 16 | String result 17 | 18 | String serviceName 19 | 20 | String url 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/exception/LoginException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.exception; 2 | 3 | public class LoginException extends FailException { 4 | 5 | private static final long serialVersionUID = 8674617502387938483L; 6 | 7 | private LoginException() { 8 | super("登录异常!"); 9 | } 10 | 11 | private LoginException(String name) { 12 | super(name); 13 | } 14 | 15 | public static void fail(String name) { 16 | throw new LoginException(name); 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/exception/ParamException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.exception; 2 | 3 | public class ParamException extends FailException { 4 | 5 | private static final long serialVersionUID = -5079364420579956243L; 6 | 7 | private ParamException() { 8 | super("参数错误!"); 9 | } 10 | 11 | private ParamException(String name) { 12 | super(name); 13 | } 14 | 15 | public static void fail(String name) { 16 | throw new ParamException(name); 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/response/TestCaseListBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例列表 7 | */ 8 | class TestCaseListBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = -184894651958; 11 | 12 | Integer id 13 | 14 | String user 15 | 16 | String envName 17 | 18 | String apiName 19 | 20 | Integer isMyself 21 | 22 | Integer isUsed 23 | 24 | String name 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/mapper/CommonMapper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.mapper; 2 | 3 | import com.okay.family.common.bean.RequestSaveBean; 4 | 5 | import java.util.HashMap; 6 | import java.util.List; 7 | 8 | public interface CommonMapper { 9 | 10 | List> findAllHost(); 11 | 12 | int saveRequest(RequestSaveBean bean); 13 | 14 | String getEnvHostLast(); 15 | 16 | String getHost(int envId, int service_id); 17 | 18 | int lock(long lock); 19 | 20 | int unlock(long lock); 21 | 22 | void clearLock(String date); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 6 | import org.springframework.web.socket.server.standard.ServerEndpointExporter; 7 | 8 | @Configuration 9 | @EnableWebSocket 10 | public class WebSocketConfig { 11 | @Bean 12 | public ServerEndpointExporter serverEndpoint() { 13 | return new ServerEndpointExporter(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/basedata/FamilyConstant.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.basedata; 2 | 3 | import com.okay.family.fun.config.PropertyUtils; 4 | 5 | /** 6 | * 从配置文件读取的常量 7 | */ 8 | public class FamilyConstant { 9 | 10 | static PropertyUtils.Property property = PropertyUtils.getProperties("family"); 11 | 12 | 13 | /** 14 | * 是否区分登录选项,针对stress环境临时设置 15 | */ 16 | public static boolean TEA_WEB_LOGIN = property.getPropertyBoolean("teaweblogin"); 17 | 18 | public static boolean OUTPUT = property.getPropertyBoolean("output_key"); 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/interfaces/IMessage.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.interfaces; 2 | 3 | public interface IMessage { 4 | /** 5 | * 发送系统异常 6 | */ 7 | public void sendSystemMessage(); 8 | 9 | /** 10 | * 发送功能异常 11 | */ 12 | public void sendFunctionMessage(); 13 | 14 | /** 15 | * 发送业务异常 16 | */ 17 | public void sendBusinessMessage(); 18 | 19 | /** 20 | * 发送程序异常 21 | */ 22 | public void sendCodeMessage(); 23 | 24 | /** 25 | * 提醒推送 26 | */ 27 | public void sendRemindMessage(); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/DelCollectionBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | import javax.validation.constraints.Min 6 | import javax.validation.constraints.NotNull 7 | 8 | class DelCollectionBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = -15498489416; 11 | 12 | @NotNull(message = "uid不能为空") 13 | @Min(value = 1L) 14 | Integer uid 15 | 16 | @NotNull(message = "groupId不能为空") 17 | @Min(value = 1L) 18 | Integer groupId 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/common/SimpleBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.common 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 通用bean,用户返回名称列表 7 | */ 8 | class SimpleBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = 168461652315615; 11 | 12 | Integer id 13 | 14 | String name 15 | 16 | SimpleBean(Integer id, String name) { 17 | this.id = id 18 | this.name = name 19 | } 20 | 21 | public static SimpleBean getBean(int id, String name) { 22 | new SimpleBean(id, name) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/request/CaseEditRecord.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 测试用例编辑历史 7 | */ 8 | class CaseEditRecord extends AbstractBean { 9 | 10 | private static final long serialVersionUID = -6290432268998729332L; 11 | 12 | Integer caseId 13 | 14 | Integer editor 15 | 16 | Integer type 17 | 18 | CaseEditRecord(Integer caseId, Integer editor, Integer type) { 19 | this.caseId = caseId 20 | this.editor = editor 21 | this.type = type 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/response/CollectionRunSimpleResutl.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例集运行的简单结果 7 | */ 8 | class CollectionRunSimpleResutl extends AbstractBean { 9 | 10 | private static final long serialVersionUID = 43439867210; 11 | 12 | Integer runId 13 | 14 | Integer caseNum 15 | 16 | String start 17 | 18 | String end 19 | 20 | String result 21 | 22 | Integer success 23 | 24 | Integer fail 25 | 26 | Integer unrun 27 | 28 | Integer userError 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/exception/FailException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.exception; 2 | 3 | public class FailException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = -7041169491254546905L; 6 | 7 | public FailException() { 8 | super("FunTester"); 9 | } 10 | 11 | protected FailException(String message) { 12 | super(message); 13 | } 14 | 15 | public static void fail(String message) { 16 | throw new FailException(message); 17 | } 18 | 19 | public static void fail() { 20 | throw new FailException(); 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/common/DelBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.common 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | import javax.validation.constraints.Min 6 | import javax.validation.constraints.NotNull 7 | 8 | /** 9 | * 删除,一些比较简单的接口请求对象也可采用 10 | */ 11 | class DelBean extends AbstractBean { 12 | 13 | private static final long serialVersionUID = 89458151651564747L; 14 | 15 | @NotNull(message = "id不能为空") 16 | @Min(value = 1L, message = "id参数错误") 17 | Integer id 18 | 19 | @NotNull(message = "uid不能为空") 20 | @Min(value = 1L,message = "用户id错误") 21 | Integer uid 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/code/DataBaseCode.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.code 2 | 3 | import com.okay.family.fun.base.interfaces.ReturnCode 4 | 5 | enum DataBaseCode implements ReturnCode { 6 | 7 | ONLY_KEY_FAIL(200, "数据重复,无法操作"), 8 | MYBATIS_FAIL(201, "系统错误"), 9 | MYBATIS_CONFIG_ERROR(203, "配置错误") 10 | 11 | int code 12 | 13 | String desc 14 | 15 | DataBaseCode(int code, String desc) { 16 | this.code = code 17 | this.desc = desc 18 | } 19 | 20 | @Override 21 | int getCode() { 22 | return code 23 | } 24 | 25 | @Override 26 | String getDesc() { 27 | return desc 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/pubdata/PubDataDetailBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.pubdata 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import com.okay.family.fun.config.Constant 6 | /** 7 | * 用于存储公共数据的每一条对象,后面属性默认方便前端展示处理 8 | */ 9 | class PubDataDetailBean extends AbstractBean { 10 | 11 | private static final long serialVersionUID = 62931721071606L; 12 | 13 | String name 14 | 15 | String demo 16 | 17 | String requirement = "R" 18 | 19 | JSONArray children = new JSONArray(0) 20 | 21 | String dataType = "string" 22 | 23 | String remark = Constant.EMPTY 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/ScheduledConfig.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.TaskScheduler; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 7 | 8 | @Configuration 9 | public class ScheduledConfig { 10 | 11 | @Bean 12 | public TaskScheduler taskScheduler() { 13 | ThreadPoolTaskScheduler scheduling = new ThreadPoolTaskScheduler(); 14 | scheduling.setPoolSize(10); 15 | scheduling.initialize(); 16 | return scheduling; 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testuser/response/TestUserBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testuser.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | /** 5 | * 测试用户bean,不包含certificate 6 | */ 7 | class TestUserBean extends AbstractBean { 8 | 9 | private static final long serialVersionUID = -15924867071153477L; 10 | 11 | Integer id 12 | 13 | String envName 14 | 15 | Integer envId 16 | 17 | String user 18 | 19 | String roleName 20 | 21 | Integer roleId 22 | 23 | String password 24 | 25 | String phone 26 | 27 | String des 28 | 29 | String status 30 | 31 | String create_time 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/code/PubDataCode.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.code 2 | 3 | import com.okay.family.fun.base.interfaces.ReturnCode 4 | 5 | enum PubDataCode implements ReturnCode { 6 | 7 | ADD_FAIL(2000, "公共数据添加失败"), 8 | NO_MATCH_FAIL(2001, "没有匹配记录,删除失败"), 9 | NO_CHANGE_FAIL(2002, "没有匹配记录/与原有内容一致,无法更改") 10 | 11 | int code 12 | 13 | String desc 14 | 15 | PubDataCode(int code, String desc) { 16 | this.code = code 17 | this.desc = desc 18 | } 19 | 20 | @Override 21 | int getCode() { 22 | return code 23 | } 24 | 25 | @Override 26 | String getDesc() { 27 | return desc 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/PubStatus.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum PubStatus { 7 | 8 | ALREADY(1, "已共享"), 9 | NOTYET(2, "未共享") 10 | 11 | int code 12 | 13 | int desc 14 | 15 | PubStatus(int code, int desc) { 16 | this.code = code 17 | this.desc = desc 18 | } 19 | 20 | static JSONArray getAll() { 21 | JSONArray result = new JSONArray() 22 | PubStatus.values().each {x -> 23 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 24 | } 25 | result 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/response/ListCollectionBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例集列表展示 7 | */ 8 | class ListCollectionBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = -14894856161; 11 | 12 | 13 | Integer id 14 | 15 | /** 16 | * 0 非本人 1本人 17 | */ 18 | Integer isMyself 19 | /** 20 | * 1已共享;2未共享 21 | */ 22 | Integer isShare 23 | 24 | String result 25 | 26 | String name 27 | 28 | String envName 29 | 30 | Integer envId 31 | 32 | String createTime 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/DelStatus.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum DelStatus { 7 | 8 | NOT_YET(1, "还未删除,默认状态"), 9 | ALREADY(2, "已经删除") 10 | 11 | int code 12 | 13 | String desc 14 | 15 | DelStatus(int code, String desc) { 16 | this.code = code 17 | this.desc = desc 18 | } 19 | 20 | static JSONArray getAll() { 21 | JSONArray result = new JSONArray() 22 | DelStatus.values().each {x -> 23 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 24 | } 25 | result 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/exception/CaseException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.exception; 2 | 3 | import com.okay.family.fun.base.exception.FailException; 4 | 5 | public class CaseException extends FailException { 6 | 7 | private static final long serialVersionUID = 6515648130665053L; 8 | 9 | public CaseException() { 10 | super("用例错误!"); 11 | } 12 | 13 | protected CaseException(String message) { 14 | super(message); 15 | } 16 | 17 | public static void fail() { 18 | throw new CaseException(); 19 | } 20 | 21 | public static void fail(String message) { 22 | throw new CaseException(message); 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/config/SysInit.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.config; 2 | 3 | 4 | import com.okay.family.fun.frame.SourceCode; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * 存放一些系统初始化的方法,可被外部调用 10 | */ 11 | public class SysInit extends SourceCode { 12 | 13 | private static Logger logger = LoggerFactory.getLogger(SysInit.class); 14 | 15 | /** 16 | * 是否是黑名单的host 17 | *

先检验fv1314和本地local还有10.10.的地址,然后校验配置文件中的host name

18 | * 19 | * @param name 20 | * @return 21 | */ 22 | public static boolean isBlack(String name) { 23 | return name.contains("10.10") || name.contains("local"); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/CaseCollectionEditRecord.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例集编辑记录 7 | */ 8 | class CaseCollectionEditRecord extends AbstractBean { 9 | 10 | private static final long serialVersionUID = 7314229831207231048L; 11 | 12 | 13 | Integer collectionId 14 | 15 | Integer editor 16 | 17 | String create_time 18 | 19 | Integer type 20 | 21 | CaseCollectionEditRecord(int collectionId, int editor, int type) { 22 | this.collectionId = collectionId 23 | this.editor = editor 24 | this.type = type 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/exception/CommonException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.exception; 2 | 3 | import com.okay.family.fun.base.exception.FailException; 4 | 5 | public class CommonException extends FailException { 6 | 7 | private static final long serialVersionUID = -2409699175834194030L; 8 | 9 | private CommonException() { 10 | super("通用错误!"); 11 | } 12 | 13 | protected CommonException(String message) { 14 | super(message); 15 | } 16 | 17 | public static void fail() { 18 | throw new CommonException(); 19 | } 20 | 21 | public static void fail(String message) { 22 | throw new CommonException(message); 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/threadpool/OkayThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.threadpool; 2 | 3 | import java.util.concurrent.LinkedBlockingQueue; 4 | import java.util.concurrent.ThreadPoolExecutor; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * 自定义线程池,用例批量运行用例,非并发测试线程池 9 | */ 10 | public class OkayThreadPool { 11 | 12 | private static ThreadPoolExecutor executor = createPool(); 13 | 14 | public static void addSyncWork(Runnable runnable) { 15 | executor.execute(runnable); 16 | } 17 | 18 | private static ThreadPoolExecutor createPool() { 19 | return new ThreadPoolExecutor(16, 100, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/CaseAvailableStatus.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum CaseAvailableStatus { 7 | 8 | OK(1, "可用"), 9 | NO(2, "不可用"), 10 | 11 | int code 12 | 13 | String desc 14 | 15 | CaseAvailableStatus(int code, String desc) { 16 | this.code = code 17 | this.desc = desc 18 | } 19 | 20 | static JSONArray getAll() { 21 | JSONArray result = new JSONArray() 22 | CaseAvailableStatus.values().each {x -> 23 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 24 | } 25 | result 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/exception/UserStatusException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.exception; 2 | 3 | import com.okay.family.fun.base.exception.FailException; 4 | 5 | public class UserStatusException extends FailException { 6 | 7 | private static final long serialVersionUID = -6307468548130665053L; 8 | 9 | public UserStatusException() { 10 | super("用户状态错误!"); 11 | } 12 | 13 | protected UserStatusException(String message) { 14 | super(message); 15 | } 16 | 17 | public static void fail() { 18 | throw new UserStatusException(); 19 | } 20 | 21 | public static void fail(String message) { 22 | throw new UserStatusException(message); 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/mapper/PubDataMapper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.mapper; 2 | 3 | import com.okay.family.common.bean.common.DelBean; 4 | import com.okay.family.common.bean.pubdata.request.EditPubBean; 5 | import com.okay.family.common.bean.pubdata.response.PubDataBean; 6 | import com.okay.family.common.bean.pubdata.request.SavePubDataBean; 7 | 8 | import java.util.List; 9 | 10 | public interface PubDataMapper { 11 | 12 | List getDatasByEnv(int uid, int envId); 13 | 14 | List getAllDatas(int uid); 15 | 16 | int add(EditPubBean bean); 17 | 18 | int updateDataAttribute(EditPubBean bean); 19 | 20 | int delData(DelBean bean); 21 | 22 | int saveData(SavePubDataBean bean); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/UserState.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum UserState { 7 | 8 | // DEFAULT(1, "默认"),//暂时不用 9 | OK(2, "可用"), 10 | NO(3, "不可用"), 11 | CANNOT(4, "无法验证") 12 | 13 | int code 14 | 15 | String desc 16 | 17 | UserState(int code, String desc) { 18 | this.code = code 19 | this.desc = desc 20 | } 21 | 22 | static JSONArray getAll() { 23 | JSONArray result = new JSONArray() 24 | UserState.values().each {x -> 25 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 26 | } 27 | result 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/CaseEditType.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum CaseEditType { 7 | 8 | CREATE(1, "创建用例"), 9 | EDIT_ATTRIBUTE(2, "修改用例属性"), 10 | EDIT_DATA(3, "修改用例数据") 11 | 12 | int code 13 | 14 | String desc 15 | 16 | CaseEditType(int code, String desc) { 17 | this.code = code 18 | this.desc = desc 19 | } 20 | 21 | static JSONArray getAll() { 22 | JSONArray result = new JSONArray() 23 | CaseEditType.values().each {x -> 24 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 25 | } 26 | result 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/CollectionStatus.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum CollectionStatus { 7 | 8 | 9 | DEFAULT(1, "未测试"), 10 | SUCCESS(2, "成功"), 11 | FAIL(3, "失败") 12 | 13 | int code 14 | 15 | String desc 16 | 17 | CollectionStatus(int code, String desc) { 18 | this.code = code 19 | this.desc = desc 20 | } 21 | 22 | static JSONArray getAll() { 23 | JSONArray result = new JSONArray() 24 | CollectionStatus.values().each {x -> 25 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 26 | } 27 | result 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/exception/CaseCollecionException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.exception; 2 | 3 | import com.okay.family.fun.base.exception.FailException; 4 | 5 | public class CaseCollecionException extends FailException { 6 | 7 | private static final long serialVersionUID = 6515648130665053L; 8 | 9 | public CaseCollecionException() { 10 | super("用例集错误!"); 11 | } 12 | 13 | protected CaseCollecionException(String message) { 14 | super(message); 15 | } 16 | 17 | public static void fail() { 18 | throw new CaseCollecionException(); 19 | } 20 | 21 | public static void fail(String message) { 22 | throw new CaseCollecionException(message); 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/code/TestUserCode.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.code 2 | 3 | import com.okay.family.fun.base.interfaces.ReturnCode 4 | 5 | enum TestUserCode implements ReturnCode { 6 | 7 | NO_USER(1000, "用户不存在"), 8 | CHECK_FAIL(1001, "用户校验失败"), 9 | UPDATE_USER_FAIL(1002, "没有匹配记录/与原有内容一致,无法更改"), 10 | DEL_USER_FAIL(1003, "删除用户失败"), 11 | ADD_USER_FAIL(1004, "添加用户失败") 12 | 13 | int code 14 | 15 | String desc 16 | 17 | TestUserCode(int code, String desc) { 18 | this.code = code 19 | this.desc = desc 20 | } 21 | 22 | 23 | @Override 24 | int getCode() { 25 | return code 26 | } 27 | 28 | @Override 29 | String getDesc() { 30 | return desc 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/RunResult.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum RunResult { 7 | 8 | SUCCESS(2, "成功"), 9 | FAIL(3, "失败"), 10 | UNRUN(4, "无法运行"), 11 | USER_ERROR(5, "用户错误") 12 | 13 | int code 14 | 15 | String desc 16 | 17 | RunResult(int code, String desc) { 18 | this.code = code 19 | this.desc = desc 20 | } 21 | 22 | static JSONArray getAll() { 23 | JSONArray result = new JSONArray() 24 | RunResult.values().each {x -> 25 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 26 | } 27 | result 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/wapper/LogConfig.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.wapper; 2 | 3 | import org.springframework.web.servlet.config.annotation.InterceptorRegistration; 4 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | //@Configuration 8 | public class LogConfig implements WebMvcConfigurer { 9 | 10 | @Override 11 | public void addInterceptors(InterceptorRegistry registry) { 12 | //注册TestInterceptor拦截器 13 | InterceptorRegistration registration = registry.addInterceptor(new CommonInterceptor()); 14 | registration.addPathPatterns("/**"); //所有路径都被拦截 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/IPubDataService.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service; 2 | 3 | import com.okay.family.common.bean.common.DelBean; 4 | import com.okay.family.common.bean.pubdata.request.EditPubBean; 5 | import com.okay.family.common.bean.pubdata.response.PubDataBean; 6 | import com.okay.family.common.bean.pubdata.request.SavePubDataBean; 7 | 8 | import java.util.List; 9 | 10 | public interface IPubDataService { 11 | 12 | List getAllDatas(int uid); 13 | 14 | List getDatasByEnv(int uid, int envId); 15 | 16 | int addData(EditPubBean bean); 17 | 18 | int delData(DelBean bean); 19 | 20 | int updateDataAttribute(EditPubBean bean); 21 | 22 | int saveData(SavePubDataBean bean); 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/code/CollectionCode.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.code 2 | 3 | import com.okay.family.fun.base.interfaces.ReturnCode 4 | 5 | enum CollectionCode implements ReturnCode { 6 | 7 | ADD_COLLECTION_FAIL(4001, "添加测试用例集失败"), 8 | NO_CHANGE_FAIL(4002, "没有匹配记录/与原有内容一致,无法更改"), 9 | DEL_COLLECTION_FAIL(4003, "没有匹配记录,无法删除"), 10 | DEL_CASE_FAIL(4004, "没有匹配记录,无法删除") 11 | 12 | 13 | int code 14 | 15 | String desc 16 | 17 | @Override 18 | int getCode() { 19 | return code 20 | } 21 | 22 | @Override 23 | String getDesc() { 24 | return desc 25 | } 26 | 27 | CollectionCode(int code, String desc) { 28 | this.code = code 29 | this.desc = desc 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/DelCaseCollectionRelationBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | import javax.validation.constraints.Min 6 | import javax.validation.constraints.NotNull 7 | /** 8 | * 用例用例集和用例关联关系 9 | */ 10 | class DelCaseCollectionRelationBean extends AbstractBean { 11 | 12 | private static final long serialVersionUID = 38498348343489; 13 | 14 | @NotNull(message = "uid不能为空") 15 | @Min(value = 1L) 16 | Integer uid 17 | 18 | @NotNull(message = "apiId不能为空") 19 | @Min(value = 1L) 20 | Integer apiId 21 | 22 | @NotNull(message = "groupId不能为空") 23 | @Min(value = 1L) 24 | Integer groupId 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/CaseLevel.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum CaseLevel { 7 | 8 | 9 | DEAFULT(1, "默认等级"), 10 | HIGH(2, "高运行等级"), 11 | NORMAL(3, "普通运行等级"), 12 | LOW(4, "低运行等级") 13 | 14 | 15 | int code 16 | 17 | String desc 18 | 19 | CaseLevel(int code, String desc) { 20 | this.code = code 21 | this.desc = desc 22 | } 23 | 24 | static JSONArray getAll() { 25 | JSONArray result = new JSONArray() 26 | CaseLevel.values().each {x -> 27 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 28 | } 29 | result 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/CollectionEditBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | import javax.validation.constraints.Min 6 | import javax.validation.constraints.NotBlank 7 | import javax.validation.constraints.NotNull 8 | 9 | /** 10 | * 编辑用例集 11 | */ 12 | class CollectionEditBean extends AbstractBean { 13 | 14 | private static final long serialVersionUID = 2342423490869045; 15 | 16 | @NotNull(message = "uid不能为空") 17 | @Min(value = 1L) 18 | Integer uid 19 | 20 | @NotNull(message = "groupId不能为空") 21 | @Min(value = 1L) 22 | Integer groupId 23 | 24 | @NotBlank(message = "name不能为空") 25 | String name 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/code/TestCaseCode.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.code 2 | 3 | import com.okay.family.fun.base.interfaces.ReturnCode 4 | 5 | enum TestCaseCode implements ReturnCode { 6 | 7 | ADD_CASE_FAIL(3000, "添加测试用例失败"), 8 | DEL_CASE_FAIL(3001, "删除测试用例失败"), 9 | NO_CHANGE_FAIL(3002, "没有匹配记录/与原有内容一致,无法更改"), 10 | COPY_CASE_FAIL(3003, "复制用例错误"), 11 | SAVE_CASE_ERROR(3004,"保存用例数据失败") 12 | 13 | int code 14 | 15 | String desc 16 | 17 | TestCaseCode(int code, String desc) { 18 | this.code = code 19 | this.desc = desc 20 | } 21 | 22 | @Override 23 | int getCode() { 24 | return code 25 | } 26 | 27 | @Override 28 | String getDesc() { 29 | return desc 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/SearchCollectionNoPageBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import org.hibernate.validator.constraints.Range 6 | 7 | import javax.validation.constraints.NotNull 8 | 9 | class SearchCollectionNoPageBean extends AbstractBean{ 10 | 11 | private static final long serialVersionUID = -324894815616518798; 12 | 13 | 14 | @NotNull(message = "uid不能为空") 15 | Integer uid 16 | 17 | @NotNull(message = "envId不能为空") 18 | @Range(min = 1L, max = OkayConstant.ENV, message = "环境ID参数错误") 19 | Integer envId 20 | 21 | @NotNull(message = "query不能为空") 22 | String query 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/pubdata/request/SavePubDataBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.pubdata.request 2 | 3 | import com.okay.family.common.bean.pubdata.PubDataDetailBean 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | 6 | import javax.validation.constraints.Min 7 | import javax.validation.constraints.NotEmpty 8 | import javax.validation.constraints.NotNull 9 | 10 | class SavePubDataBean extends AbstractBean { 11 | 12 | private static final long serialVersionUID = 6293172188474L; 13 | 14 | @NotNull(message = "id不能为空") 15 | @Min(value = 1L) 16 | Integer id 17 | 18 | @NotNull(message = "uid不能为空") 19 | @Min(value = 1L) 20 | Integer uid 21 | 22 | @NotEmpty(message = "公共数据不能为空") 23 | List list 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/Identity.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum Identity { 7 | 8 | STU_PAD(1, "学生pad"), 9 | STU_WEB(2, "学生空间"), 10 | TEA_PAD(3, "老师pad"), 11 | TEA_WEB(4, "教师空间"), 12 | PUB_WEB(5, "公立校"), 13 | STU_APP(6, "OK学生") 14 | 15 | int code 16 | 17 | def desc 18 | 19 | Identity(int code, def desc) { 20 | this.code = code 21 | this.desc = desc 22 | } 23 | 24 | static JSONArray getAll() { 25 | JSONArray result = new JSONArray() 26 | Identity.values().each {x -> 27 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 28 | } 29 | result 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/response/CaseRunDetailBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.response 2 | 3 | import com.alibaba.fastjson.JSONObject 4 | import com.okay.family.common.bean.testcase.CaseVerifyBean 5 | import com.okay.family.fun.base.bean.AbstractBean 6 | 7 | class CaseRunDetailBean extends AbstractBean{ 8 | 9 | private static final long serialVersionUID = -12987746646546; 10 | 11 | Integer runId 12 | 13 | Integer mark 14 | 15 | Integer caseId 16 | 17 | Integer code 18 | 19 | String requestid 20 | 21 | Integer httpCode 22 | 23 | Integer cost 24 | 25 | List verify 26 | 27 | JSONObject headers 28 | 29 | JSONObject params 30 | 31 | JSONObject response 32 | 33 | String create_time 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/RequestType.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | /** 7 | * 接口请求方式,get postform, postjson,枚举类 8 | */ 9 | enum RequestType { 10 | 11 | GET(1, "GET"), 12 | POST_JSON(2, "POST-JSON"), 13 | POST_FORM(3, "POST-FORM") 14 | 15 | int code 16 | 17 | String desc 18 | 19 | RequestType(int code, String desc) { 20 | this.code = code 21 | this.desc = desc 22 | } 23 | 24 | static JSONArray getAll() { 25 | JSONArray result = new JSONArray() 26 | RequestType.values().each {x -> 27 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 28 | } 29 | result 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/CollectionRunResultRecord.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | import com.okay.family.fun.config.Constant 5 | 6 | /** 7 | * 用例集运行结果 8 | */ 9 | class CollectionRunResultRecord extends AbstractBean{ 10 | 11 | private static final long serialVersionUID = 48438627439874932; 12 | 13 | Integer collectionId 14 | 15 | Integer uid 16 | 17 | Integer envId 18 | 19 | Integer runId 20 | 21 | String name = Constant.EMPTY 22 | 23 | Integer caseNum 24 | 25 | Integer result 26 | 27 | Integer success 28 | 29 | Integer fail 30 | 31 | Integer unrun 32 | 33 | Integer userError 34 | 35 | String start 36 | 37 | String end 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/enums/CollectionEditType.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.enums 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.common.SimpleBean 5 | 6 | enum CollectionEditType { 7 | 8 | CREATE(1, "创建用例集"), 9 | ADD_CASE(2, "添加测试用例"), 10 | DEL_CASE(3, "删除测试用例"), 11 | EDIT_NAME(4, "编辑用例集名称"), 12 | SHARE(5, "共享测试用例集") 13 | 14 | int code 15 | 16 | String desc 17 | 18 | CollectionEditType(int code, String desc) { 19 | this.code = code 20 | this.desc = desc 21 | } 22 | 23 | static JSONArray getAll() { 24 | JSONArray result = new JSONArray() 25 | CollectionEditType.values().each {x -> 26 | result << SimpleBean.getBean(x.getCode(), x.getDesc()) 27 | } 28 | result 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/response/CollectionCaseInfoBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.response 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | /** 6 | * 用例集信息 7 | */ 8 | class CollectionCaseInfoBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = 69384703278; 11 | 12 | Integer id 13 | 14 | Integer uid 15 | 16 | Integer envId 17 | 18 | String groupName 19 | 20 | /** 21 | * 0非本人 1 本人 22 | */ 23 | Integer isMyself 24 | 25 | List list 26 | 27 | def copyFrom(CollectionCaseInfoBean bean) { 28 | this.envId = bean.getEnvId() 29 | this.groupName = bean.getGroupName() 30 | this.isMyself = bean.getIsMyself() 31 | this.uid = null 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/code/CommonCode.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.code; 2 | 3 | import com.okay.family.fun.base.interfaces.ReturnCode 4 | import com.okay.family.fun.config.Constant; 5 | 6 | enum CommonCode implements ReturnCode { 7 | 8 | 9 | FAIL(Constant.TEST_ERROR_CODE, "失败"), 10 | SUCCESS(0, "成功"), 11 | PARAMS_ERROR(100, "常用参数错误!"), 12 | BIND_ERROR(101, "参数验证错误!"), 13 | UNKNOW_ERROR(102, "未知错误"), 14 | REQUESTID_ERROR(103, "requestid错误") 15 | 16 | int code 17 | 18 | String desc 19 | 20 | CommonCode(int code, String desc) { 21 | this.code = code 22 | this.desc = desc 23 | } 24 | 25 | 26 | @Override 27 | int getCode() { 28 | return code 29 | } 30 | 31 | @Override 32 | String getDesc() { 33 | return desc 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/exception/RequestException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.exception; 2 | 3 | import org.apache.http.client.methods.HttpRequestBase; 4 | 5 | public class RequestException extends FailException { 6 | 7 | private static final long serialVersionUID = 7916010541762451964L; 8 | 9 | private RequestException() { 10 | super("错误的请求!"); 11 | } 12 | 13 | private RequestException(HttpRequestBase request) { 14 | super(request.toString()); 15 | } 16 | 17 | public RequestException(String message) { 18 | super(message); 19 | } 20 | 21 | public static void fail(HttpRequestBase base) { 22 | throw new RequestException(base); 23 | } 24 | 25 | public static void fail(String message) { 26 | throw new RequestException(message); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/request/CaseEditRecordQueryBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | import org.hibernate.validator.constraints.Range 5 | 6 | import javax.validation.constraints.Min 7 | import javax.validation.constraints.NotNull 8 | 9 | /** 10 | * 用例编辑记录 11 | */ 12 | class CaseEditRecordQueryBean extends AbstractBean { 13 | 14 | private static final long serialVersionUID = 3289389274983L; 15 | 16 | @NotNull(message = "id不能为空") 17 | @Min(value = 1L,message = "id错误!") 18 | Integer id 19 | 20 | @NotNull(message = "pageNum不能为空") 21 | @Min(value = 1L) 22 | Integer pageNum 23 | 24 | @NotNull(message = "pageSize不能为空") 25 | @Range(min = 5L, max = 20L, message = "每页显示数量设置错误") 26 | Integer pageSize 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/request/CaseSearchNoPageBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import org.hibernate.validator.constraints.Range 6 | 7 | import javax.validation.constraints.Min 8 | import javax.validation.constraints.NotNull 9 | 10 | class CaseSearchNoPageBean extends AbstractBean { 11 | 12 | private static final long serialVersionUID = -654984894165; 13 | 14 | @NotNull(message = "uid不能为空") 15 | @Min(value = 1L) 16 | Integer uid 17 | 18 | @NotNull(message = "envId不能为空") 19 | @Range(min = 0L, max = OkayConstant.ENV, message = "环境变量参数错误") 20 | Integer envId 21 | 22 | @NotNull(message = "apiId不能为空") 23 | @Min(value = 1L) 24 | Integer apiId 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/basedata/OkayMethod.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.basedata 2 | 3 | import com.alibaba.fastjson.JSONObject 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import com.okay.family.fun.frame.SourceCode 6 | 7 | class OkayMethod extends SourceCode { 8 | 9 | public static JSONObject getIdResult(def id) { 10 | return getSimpleJson(OkayConstant.SIMPLER_RESULT_KEY_ID, id) 11 | } 12 | 13 | public static JSONObject getNameResult(def name) { 14 | return getSimpleJson(OkayConstant.SIMPLER_RESULT_KEY_ID, name) 15 | } 16 | 17 | public static JSONObject getSimpleResult(AbstractBean bean) { 18 | try { 19 | getIdResult bean.getProperty(OkayConstant.SIMPLER_RESULT_KEY_ID) 20 | } catch (MissingPropertyException e) { 21 | getIdResult(-2) 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/RunCollectionBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import org.hibernate.validator.constraints.Range 6 | 7 | import javax.validation.constraints.Min 8 | import javax.validation.constraints.NotNull 9 | 10 | /** 11 | * 运行用例集 12 | */ 13 | class RunCollectionBean extends AbstractBean { 14 | 15 | private static final long serialVersionUID = 9733934389389749; 16 | 17 | @NotNull(message = "groupId不能为空") 18 | @Min(value = 1L) 19 | Integer groupId 20 | 21 | @NotNull(message = "uid不能为空") 22 | @Min(value = 1L) 23 | Integer uid 24 | 25 | @NotNull(message = "envId不能为空") 26 | @Range(min = 1L, max = OkayConstant.ENV, message = "环境ID参数错误") 27 | Integer envId 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/Task.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.utils.Time 5 | import com.okay.family.service.ICommonService 6 | import org.slf4j.Logger 7 | import org.slf4j.LoggerFactory 8 | import org.springframework.scheduling.annotation.Scheduled 9 | import org.springframework.stereotype.Component 10 | 11 | @Component 12 | class Task { 13 | 14 | private static Logger logger = LoggerFactory.getLogger(Task.class) 15 | 16 | ICommonService commonService 17 | 18 | Task(ICommonService commonService) { 19 | this.commonService = commonService 20 | } 21 | 22 | @Scheduled(cron = "0 0/10 * * * ?") 23 | def saveRequestBean() { 24 | if (OkayConstant.node == 1) commonService.clearLock() 25 | logger.info("定时任务执行完毕! 时间:{}", Time.getDate()) 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/basedata/UserLock.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.basedata; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | /** 9 | * 用户锁对象 10 | */ 11 | public class UserLock { 12 | 13 | private static Logger logger = LoggerFactory.getLogger(UserLock.class); 14 | 15 | private static ConcurrentHashMap certificates = new ConcurrentHashMap<>(); 16 | 17 | /** 18 | * 获取锁对象,用户测试用户锁 19 | * 20 | * @param id 21 | * @return 22 | */ 23 | public static Object get(int id) { 24 | certificates.compute(id, (key, value) -> 25 | { 26 | if (value == null) { 27 | value = new Object(); 28 | } 29 | return value; 30 | }); 31 | return certificates.get(id); 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/AddCollectionBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | 5 | import javax.validation.constraints.Min 6 | import javax.validation.constraints.NotBlank 7 | import javax.validation.constraints.NotEmpty 8 | import javax.validation.constraints.NotNull 9 | 10 | /** 11 | * 添加用例 12 | */ 13 | class AddCollectionBean extends AbstractBean { 14 | 15 | private static final long serialVersionUID = 589469783232L; 16 | 17 | @Min(value = 1L,message = "id参数错误") 18 | Integer id 19 | 20 | @NotNull(message = "uid不能为空") 21 | @Min(value = 1L) 22 | Integer uid 23 | 24 | @NotNull(message = "envId不能为空") 25 | @Min(value = 1L,message = "envId最小1") 26 | Integer envId 27 | 28 | @NotEmpty(message = "用例ID不能为空") 29 | Set apiList 30 | 31 | @NotBlank(message = "用例集名称不能为空") 32 | String groupName 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/response/CaseDetailBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.response 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.testcase.CaseVerifyBean 5 | import com.okay.family.fun.base.bean.AbstractBean 6 | 7 | /** 8 | * 用例详情,用于运行用例 9 | */ 10 | class CaseDetailBean extends AbstractBean { 11 | 12 | private static final long serialVersionUID = -23489723928974L; 13 | 14 | 15 | Integer id 16 | 17 | Integer apiId 18 | 19 | String name 20 | 21 | String apiName 22 | 23 | Integer envId 24 | 25 | String envName 26 | 27 | Integer serviceId 28 | 29 | String serviceName 30 | 31 | Integer moduleId 32 | 33 | String moduleName 34 | 35 | String httpType 36 | 37 | String readType 38 | 39 | JSONArray header_paras 40 | 41 | List testWish 42 | 43 | JSONArray request_paras 44 | 45 | String url 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/bean/BeanUtil.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.bean 2 | 3 | import com.alibaba.fastjson.JSON 4 | import com.alibaba.fastjson.JSONObject 5 | import com.okay.family.fun.frame.SourceCode 6 | import org.apache.commons.beanutils.BeanUtils 7 | import org.slf4j.Logger 8 | import org.slf4j.LoggerFactory 9 | 10 | class BeanUtil extends SourceCode { 11 | 12 | private static Logger logger = LoggerFactory.getLogger(BeanUtil.class) 13 | 14 | /** 15 | * 从json对象中拷贝属性到bean 16 | * @param bean 17 | * @param source 18 | * @return 19 | */ 20 | static def copyProperties(AbstractBean bean, Object source) { 21 | try { 22 | BeanUtils.copyProperties(bean, source) 23 | } catch (Exception e) { 24 | logger.warn("拷贝属性失败!", e) 25 | } 26 | } 27 | 28 | /** 29 | * 转为json 30 | * @param bean 31 | * @return 32 | */ 33 | static JSONObject toJson(AbstractBean bean) { 34 | JSON.parseObject JSON.toJSONString(bean) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/config/RequestType.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.config; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * 请求枚举类,fun备用,暂时无用,通过其他方式区分了post请求的参数格式 8 | */ 9 | public enum RequestType { 10 | 11 | GET("get"), POST("post"), FUN("fun"); 12 | 13 | static Logger logger = LoggerFactory.getLogger(RequestType.class); 14 | 15 | String name; 16 | 17 | private RequestType(String name) { 18 | this.name = name; 19 | } 20 | 21 | public static RequestType getRequestType(String name) { 22 | logger.debug("验证请求方式:{}", name); 23 | for (RequestType requestType : RequestType.values()) { 24 | if (requestType.name.equalsIgnoreCase(name)) { 25 | return requestType; 26 | } 27 | } 28 | return FUN; 29 | } 30 | 31 | /** 32 | * 获取名字 33 | * 34 | * @return 35 | */ 36 | public String getName() { 37 | return name; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/FamilyApplication.java: -------------------------------------------------------------------------------- 1 | package com.okay.family; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; 7 | import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; 8 | import org.springframework.boot.web.servlet.ServletComponentScan; 9 | import org.springframework.scheduling.annotation.EnableAsync; 10 | import org.springframework.transaction.annotation.EnableTransactionManagement; 11 | 12 | 13 | @MapperScan(value = "com.okay.family.mapper") 14 | @ServletComponentScan 15 | @EnableAsync 16 | @EnableTransactionManagement 17 | @SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) 18 | public class FamilyApplication { 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(FamilyApplication.class, args); 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/mapper/TestUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.mapper; 2 | 3 | import com.okay.family.common.bean.common.DelBean; 4 | import com.okay.family.common.bean.testuser.request.EditUserBean; 5 | import com.okay.family.common.bean.testuser.request.SearchUserBean; 6 | import com.okay.family.common.bean.testuser.response.TestUserBean; 7 | import com.okay.family.common.bean.testuser.TestUserCheckBean; 8 | 9 | import java.util.List; 10 | 11 | public interface TestUserMapper { 12 | 13 | List findUsers(SearchUserBean bean); 14 | 15 | int addUser(EditUserBean user); 16 | 17 | TestUserCheckBean findUser(int id); 18 | 19 | /** 20 | * 更新测试用户状态和用户凭据 21 | * 22 | * @param user 23 | * @return 24 | */ 25 | int updateUser(EditUserBean user); 26 | 27 | /** 28 | * 此处包括更新用户最近一次编辑时间,直接调用表示更新时间,如果是登录后更新,必需加分布式锁 29 | * 30 | * @param user 31 | * @return 32 | */ 33 | int updateUserStatus(TestUserCheckBean user); 34 | 35 | int delUser(DelBean bean); 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/basedata/ServerHost.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.basedata 2 | 3 | import com.okay.family.fun.frame.SourceCode 4 | import org.slf4j.Logger 5 | import org.slf4j.LoggerFactory 6 | 7 | import java.util.concurrent.ConcurrentHashMap 8 | 9 | class ServerHost extends SourceCode { 10 | 11 | private static Logger logger = LoggerFactory.getLogger(ServerHost.class) 12 | 13 | static Map hosts = new ConcurrentHashMap<>() 14 | 15 | static Map timeout = new ConcurrentHashMap<>() 16 | 17 | public static String getHost(int id) { 18 | if ((getMark() - timeout.getOrDefault(id,0) > OkayConstant.HOST_TIMEOUT) || !hosts.containsKey(id)) null 19 | else hosts.get(id) 20 | } 21 | 22 | static String getHost(int envId, int serviceId) { 23 | getHost(serviceId * 10 + envId) 24 | } 25 | 26 | static void putHost(int envId, int serviceId, String host) { 27 | int key = serviceId * 10 + envId 28 | timeout.put(key, getMark()) 29 | hosts.put(key, host) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/RequestSave.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils; 2 | 3 | import com.okay.family.common.bean.RequestSaveBean; 4 | import com.okay.family.fun.frame.SourceCode; 5 | import com.okay.family.service.ICommonService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.annotation.PostConstruct; 11 | 12 | @Component 13 | public class RequestSave extends SourceCode { 14 | 15 | public static Logger logger = LoggerFactory.getLogger(RequestSave.class); 16 | 17 | private static ICommonService service; 18 | 19 | ICommonService commonService; 20 | 21 | public RequestSave(ICommonService commonService) { 22 | this.commonService = commonService; 23 | } 24 | 25 | 26 | @PostConstruct 27 | public void init() { 28 | service = this.commonService; 29 | } 30 | 31 | public static void addWork(RequestSaveBean requestSaveBean) { 32 | logger.info("记录请求:{}",requestSaveBean.toString()); 33 | service.saveRequest(requestSaveBean); 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/exception/VerifyException.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.exception; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.okay.family.fun.frame.Output; 5 | import com.okay.family.fun.frame.SourceCode; 6 | import org.apache.http.client.methods.HttpRequestBase; 7 | 8 | public class VerifyException extends FailException { 9 | 10 | private static final long serialVersionUID = 79160101017624564L; 11 | 12 | private VerifyException() { 13 | super("验证失败!"); 14 | } 15 | 16 | private VerifyException(HttpRequestBase request) { 17 | super(request.toString()); 18 | } 19 | 20 | public VerifyException(String message) { 21 | super(message); 22 | } 23 | 24 | public static void fail(JSONObject response) { 25 | Output.output(response); 26 | SourceCode.getiMessage().sendBusinessMessage(); 27 | throw new VerifyException(); 28 | } 29 | 30 | public static void fail(String message) { 31 | SourceCode.getiMessage().sendBusinessMessage(); 32 | throw new VerifyException(message); 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/pubdata/request/EditPubBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.pubdata.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import org.hibernate.validator.constraints.Length 6 | import org.hibernate.validator.constraints.Range 7 | 8 | import javax.validation.constraints.* 9 | 10 | /** 11 | * 增加,删除,更新 12 | */ 13 | class EditPubBean extends AbstractBean { 14 | 15 | private static final long serialVersionUID = 8160564161606L; 16 | 17 | Integer id 18 | 19 | @NotNull(message = "uid不能为空") 20 | @Min(value = 1L) 21 | Integer uid 22 | 23 | @NotNull(message = "envId不能为空") 24 | @Range(min = 1L, max = OkayConstant.ENV, message = "环境ID参数错误") 25 | Integer envId 26 | 27 | @NotBlank(message = "name不能为空") 28 | @Length(min = 1, max = 20, message = "公共数据集名称最大长度20") 29 | String name 30 | 31 | /** 32 | * 'add, update, delete' 33 | */ 34 | @NotBlank(message = "type不能为空") 35 | @Pattern(regexp = "add|update|delete", message = "请传正确type:add|update") 36 | String type 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/response/CollectionRunResultDetailBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.response 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.okay.family.common.bean.testcase.response.ListCaseRunResultBean 5 | import com.okay.family.fun.base.bean.AbstractBean 6 | /** 7 | * 返回给前端的测试结果 8 | */ 9 | class CollectionRunResultDetailBean extends AbstractBean { 10 | 11 | private static final long serialVersionUID = 32454657765756; 12 | /** 13 | * 用例集id 14 | */ 15 | Integer id 16 | 17 | String name 18 | 19 | String envName 20 | 21 | Integer runId 22 | 23 | Integer caseNum 24 | 25 | String result 26 | 27 | JSONArray list 28 | 29 | String startTime 30 | 31 | String endTime 32 | 33 | List caseList 34 | 35 | def copyFrom(CollectionRunResultDetailBean bean) { 36 | this.id = bean.getId() 37 | this.name = bean.getName() 38 | this.envName = bean.getEnvName() 39 | this.runId = bean.getRunId() 40 | this.caseNum = bean.getCaseNum() 41 | this.result = bean.getResult() 42 | this.list = bean.getList() 43 | this.startTime = bean.getStartTime() 44 | this.endTime = bean.getEndTime() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/threadpool/CaseParamaThread.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.threadpool; 2 | 3 | import com.okay.family.common.bean.testcase.request.CaseDataBean; 4 | import com.okay.family.fun.frame.SourceCode; 5 | import com.okay.family.utils.HandleCaseParamsUtil; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.CountDownLatch; 11 | 12 | public class CaseParamaThread extends SourceCode implements Runnable { 13 | 14 | public static Logger logger = LoggerFactory.getLogger(CaseParamaThread.class); 15 | 16 | CaseDataBean bean; 17 | 18 | ConcurrentHashMap map; 19 | 20 | CountDownLatch countDownLatch; 21 | 22 | public CaseParamaThread(CaseDataBean bean, ConcurrentHashMap map, CountDownLatch countDownLatch) { 23 | this.bean = bean; 24 | this.map = map; 25 | this.countDownLatch = countDownLatch; 26 | } 27 | 28 | @Override 29 | public void run() { 30 | try { 31 | HandleCaseParamsUtil.handleParams(bean, map); 32 | } catch (Exception e) { 33 | logger.error("处理用例参数发生错误,用例信息:{}", bean.toString(), e); 34 | }finally { 35 | countDownLatch.countDown(); 36 | } 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/response/TestCaseAttributeBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.response 2 | 3 | import com.okay.family.common.bean.common.ProjectBean 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | /** 6 | * 用例属性编辑 7 | */ 8 | class TestCaseAttributeBean extends AbstractBean { 9 | 10 | private static final long serialVersionUID = -1595563071153477L; 11 | 12 | Integer id 13 | 14 | Integer apiId 15 | 16 | String apiName 17 | 18 | Integer envId 19 | 20 | String envName 21 | 22 | Integer moduleId 23 | 24 | String moduleName 25 | 26 | String name 27 | 28 | Integer serviceId 29 | 30 | String serviceName 31 | 32 | List versionList 33 | 34 | /** 35 | * 用于异常查询结果赋值 36 | * @param bean 37 | */ 38 | def copyFrom(TestCaseAttributeBean bean) { 39 | this.id = bean.getId() 40 | this.apiId = bean.getApiId() 41 | this.apiName = bean.getApiName() 42 | this.envId = bean.getEnvId() 43 | this.envName = bean.getEnvName() 44 | this.moduleId = bean.getModuleId() 45 | this.moduleName = bean.getModuleName() 46 | this.name = bean.getName() 47 | this.serviceId = bean.getServiceId() 48 | this.serviceName = bean.getServiceName() 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | # 这是开发环境的分支 2 | 3 | 4 | ## [GitHub地址](https://github.com/JunManYuanLong/FunTester) 5 | 6 | * 开发的整个过程都写出来了,以下是内容文章的连接. 7 | 8 | # 测开笔记 9 | 10 | - [开源测试服务](https://mp.weixin.qq.com/s/ZOs0cp_vt6_iiundHaKk4g) 11 | - [我的开发日记(一)](https://mp.weixin.qq.com/s/eQgpOKbXsU9vOmxp0Xiklg) 12 | - [我的开发日记(二)](https://mp.weixin.qq.com/s/XuffL3ZmKKOgHDtH_cEYOw) 13 | - [我的开发日记(三)](https://mp.weixin.qq.com/s/a-I0agh6nWp8RLlcmbgf5w) 14 | - [我的开发日记(四)](https://mp.weixin.qq.com/s/QukXd00Mx_dbkgiXys0FNg) 15 | - [我的开发日记(五)](https://mp.weixin.qq.com/s/6P3nScsVW6MfMcyIqcA1AQ) 16 | - [我的开发日记(六)](https://mp.weixin.qq.com/s/Gz2QmukONNldSy9Fd29u5w) 17 | - [我的开发日记(七)](https://mp.weixin.qq.com/s/MjZ-nFXfQkHMsXS0fX1c1w) 18 | - [我的开发日记(八)](https://mp.weixin.qq.com/s/6ZhNcFm-gR5dhKQjEkE3Rg) 19 | - [我的开发日记(九)](https://mp.weixin.qq.com/s/VfD2T3orojGxnylr3Q5UeA) 20 | - [我的开发日记(十)](https://mp.weixin.qq.com/s/6DWth40LGbAraJi05G16Pw) 21 | - [我的开发日记(十一)](https://mp.weixin.qq.com/s/nsX5A-P6QbePHDN_Pse0_A) 22 | - [我的开发日记(十二)](https://mp.weixin.qq.com/s/XA1KJXBP3Zl-XFswXxUtvg) 23 | - [我的开发日记(十三)](https://mp.weixin.qq.com/s/_QPUu5pUlg4A_AlC5wOGkA) 24 | - [我的开发日记(十四)](https://mp.weixin.qq.com/s/Qy1YKAb3wqW_Ip2FwH7Otw) 25 | - [我的开发日记(十五)](https://mp.weixin.qq.com/s/bwkvz2t6YItQD0O_BIxpHQ) 26 | - [这些年,我写过的BUG(一)](https://mp.weixin.qq.com/s/mVTmT1FdwWl1e0BaL7Ne1g) 27 | - [这些年,我写过的BUG(二)](https://mp.weixin.qq.com/s/NMz5n0ZMf6taGb-gr1BLyw) 28 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/middle/common/Common.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.middle.common; 2 | 3 | import com.okay.family.common.basedata.OkayConstant; 4 | import com.okay.family.fun.frame.SourceCode; 5 | import com.okay.family.fun.frame.httpclient.FanLibrary; 6 | import com.okay.family.fun.utils.Time; 7 | import org.apache.http.Header; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.text.NumberFormat; 12 | import java.util.UUID; 13 | 14 | public class Common extends SourceCode { 15 | 16 | public static Logger logger = LoggerFactory.getLogger(Common.class); 17 | 18 | 19 | public static String getRequestId(String proId) { 20 | if (proId == null) { 21 | proId = "00"; 22 | } 23 | NumberFormat nf = NumberFormat.getInstance(); 24 | //设置是否使用分组 25 | nf.setGroupingUsed(false); 26 | //设置最大整数位数 27 | nf.setMaximumIntegerDigits(10); 28 | //设置最小整数位数 29 | nf.setMinimumIntegerDigits(10); 30 | return "fun_" + proId + nf.format(UUID.randomUUID().hashCode() & (0x7fffffff)); 31 | } 32 | 33 | public static Header getRequestIdHeader() { 34 | Header header = FanLibrary.getHeader(OkayConstant.REQUEST_ID, OkayConstant.REQUEST_ID_PREFIX + Time.getTimeStamp()); 35 | logger.info("requestid: {}", header.getValue()); 36 | return header; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/utils/CountTool.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.utils 2 | 3 | import com.okay.family.fun.frame.SourceCode 4 | 5 | import java.util.stream.Collectors 6 | /** 7 | * 统计出现次数相关类 8 | */ 9 | class CountTool extends SourceCode { 10 | /** 11 | * 统计数据出现的次数 12 | * 13 | * @param counts 统计的 jsonobject 对象 14 | * @param object 需要统计的数据 15 | */ 16 | static def count(Map counts, Object object) { 17 | count(counts, object, 1) 18 | } 19 | 20 | /** 21 | * 统计数据出现的次数 22 | * 23 | * @param counts 统计的 jsonobject 对象 24 | * @param object 需要统计的数据 25 | * @param num 增加值 26 | */ 27 | static def count(Map counts, Object object, int num) { 28 | counts.put(object, Integer.valueOf(counts.getOrDefault(object, 0) + num)) 29 | } 30 | 31 | /** 32 | * 统计某个list里面某个元素出现的次数 33 | * @param list 34 | * @param str 35 | * @return 36 | */ 37 | static def count(List list, def str) { 38 | list.count { s -> s.toString().equals(str.toString()) } 39 | } 40 | 41 | /** 42 | * 统计某个list里面各个元素出现的次数 43 | * collect,是一个map对象 44 | * @param list 45 | * @return 46 | */ 47 | static def count(List list) { 48 | list.stream().collect(Collectors.groupingBy { x -> x }).each { 49 | it.setValue(it.value.size()) 50 | output("元素:${it.key},次数:${it.value}") 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/thead/ParamMark.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame.thead; 2 | 3 | 4 | import com.okay.family.fun.base.constaint.ThreadBase; 5 | import com.okay.family.fun.base.interfaces.MarkThread; 6 | import com.okay.family.fun.frame.SourceCode; 7 | 8 | import java.io.Serializable; 9 | import java.util.concurrent.atomic.AtomicInteger; 10 | 11 | /** 12 | * 用于非单纯的http请求以及非HTTP请求,没有httprequestbase对象的标记方法,自己实现的虚拟类,可用户标记header固定字段或者随机参数,使用T作为参数载体,目前只能使用在T为string类才行 13 | */ 14 | public class ParamMark extends SourceCode implements MarkThread, Cloneable, Serializable { 15 | 16 | private static final long serialVersionUID = -5532592151245141262L; 17 | 18 | public static AtomicInteger threadName = new AtomicInteger(getRandomIntRange(1000, 9000)); 19 | 20 | String name; 21 | 22 | int num = getRandomIntRange(100, 999) * 1000; 23 | 24 | @Override 25 | public String mark(ThreadBase threadBase) { 26 | String m = name + num++; 27 | threadBase.t = m; 28 | return m; 29 | } 30 | 31 | @Override 32 | public ParamMark clone() { 33 | ParamMark paramMark = new ParamMark(); 34 | return paramMark; 35 | } 36 | 37 | public ParamMark() { 38 | this.name = threadName.getAndIncrement() + EMPTY; 39 | } 40 | 41 | public ParamMark(String name) { 42 | this(); 43 | this.name = name; 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/CaseRunRecord.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase 2 | 3 | import com.alibaba.fastjson.JSONObject 4 | import com.okay.family.common.basedata.OkayConstant 5 | import com.okay.family.common.bean.testcase.CaseVerifyBean 6 | import com.okay.family.common.bean.testcase.request.CaseDataBean 7 | import com.okay.family.common.enums.RunResult 8 | import com.okay.family.fun.base.bean.AbstractBean 9 | import com.okay.family.fun.config.Constant 10 | 11 | /** 12 | * 用例运行记录 13 | */ 14 | class CaseRunRecord extends AbstractBean { 15 | 16 | private static final long serialVersionUID = -159435949821153477L; 17 | 18 | Integer id 19 | 20 | Integer runId 21 | 22 | Integer mark 23 | 24 | Integer uid 25 | 26 | Integer caseId 27 | 28 | Integer code = Constant.TEST_ERROR_CODE 29 | 30 | Integer result 31 | 32 | List checkResult 33 | 34 | JSONObject params 35 | 36 | JSONObject headers 37 | 38 | JSONObject responseResult 39 | 40 | 41 | /** 42 | * 用于通用的错误类型,各类错误无法也要有运行记录 43 | * @param result 44 | * @param bean 45 | * @return 46 | */ 47 | def fail(RunResult result, CaseDataBean bean) { 48 | this.setResult(result.getCode()); 49 | this.setResponseResult(new JSONObject()); 50 | this.setCode(OkayConstant.TEST_ERROR_CODE); 51 | this.setCheckResult(bean.getTestWish()); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/ITestUserService.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service; 2 | 3 | import com.github.pagehelper.PageInfo; 4 | import com.okay.family.common.bean.common.DelBean; 5 | import com.okay.family.common.bean.testuser.request.EditUserBean; 6 | import com.okay.family.common.bean.testuser.request.SearchUserBean; 7 | import com.okay.family.common.bean.testuser.response.TestUserBean; 8 | import com.okay.family.common.bean.testuser.TestUserCheckBean; 9 | 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | public interface ITestUserService { 13 | 14 | PageInfo findUsers(SearchUserBean bean); 15 | 16 | int addUser(EditUserBean user); 17 | 18 | int updateUser(EditUserBean user); 19 | 20 | /** 21 | * 删除测试用户 22 | * 23 | * @param bean 24 | * @return 25 | */ 26 | int delUesr(DelBean bean); 27 | 28 | TestUserCheckBean findUser(int id); 29 | 30 | int updateUserStatus(TestUserCheckBean bean); 31 | 32 | /** 33 | * 验证测试用户是否可用 34 | * 35 | * @param bean 36 | * @return 37 | */ 38 | boolean checkUser(TestUserCheckBean bean); 39 | 40 | boolean checkUser(int id); 41 | 42 | /** 43 | * 获取用户凭据 44 | * 45 | * @param id 46 | * @return 47 | */ 48 | String getCertificate(int id); 49 | 50 | String getCertificate(int id, ConcurrentHashMap certificates); 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/RequestSaveBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean 2 | 3 | import com.okay.family.fun.base.bean.AbstractBean 4 | import com.okay.family.fun.base.bean.RequestInfo 5 | 6 | /** 7 | * http请求记录 8 | */ 9 | class RequestSaveBean extends AbstractBean { 10 | 11 | private static final long serialVersionUID = -15959429531153477L; 12 | 13 | /** 14 | * 接口地址 15 | */ 16 | String api 17 | 18 | Integer mark 19 | 20 | /** 21 | * 方法,get/post 22 | */ 23 | String method 24 | 25 | /** 26 | * 域名 27 | */ 28 | String host 29 | 30 | /** 31 | * 响应大小 32 | */ 33 | Integer size 34 | 35 | /** 36 | * 响应耗时 37 | */ 38 | long cost 39 | 40 | /** 41 | * 响应状态码 42 | */ 43 | Integer status 44 | 45 | /** 46 | * 响应业务code 47 | */ 48 | Integer code 49 | 50 | String requestid 51 | 52 | public RequestSaveBean(RequestInfo requestInfo, Integer size, long cost, Integer code, Integer status, String requestid,Integer mark) { 53 | this.api = requestInfo.getApiName() 54 | this.method = requestInfo.getMethod().getName() 55 | this.host = requestInfo.getHost() 56 | this.size = size 57 | this.cost = cost 58 | this.status = status 59 | this.code = code 60 | this.requestid = requestid 61 | this.mark = mark 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testuser/request/SearchUserBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testuser.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import org.hibernate.validator.constraints.Range 6 | 7 | import javax.validation.constraints.Min 8 | import javax.validation.constraints.NotNull 9 | 10 | class SearchUserBean extends AbstractBean { 11 | 12 | private static final long serialVersionUID = 894894891651651L; 13 | 14 | @NotNull(message = "uid不能为空") 15 | @Min(value = 1L,message = "uid错误") 16 | Integer uid 17 | 18 | @NotNull(message = "envId不能为空") 19 | @Range(min = 0L, max = OkayConstant.ENV, message = "环境参数错误") 20 | Integer envId 21 | 22 | @NotNull(message = "pageNum不能为空") 23 | @Min(value = 1L) 24 | Integer pageNum 25 | 26 | @NotNull(message = "pageSize不能为空") 27 | @Range(min = 5L, max = 20L, message = "每页显示数量设置错误") 28 | Integer pageSize 29 | 30 | @NotNull(message = "roleId不能为空") 31 | @Range(min = 0L, max = OkayConstant.ROLE, message = "用户身份参数错误") 32 | Integer roleId 33 | 34 | @NotNull(message = "status不能为空") 35 | @Range(min = 0L, max = OkayConstant.USER_STATUS, message = "用户状态参数错误") 36 | Integer status 37 | 38 | @NotNull(message = "query不能为空") 39 | String query 40 | 41 | @NotNull(message = "type不能为空") 42 | @Range(min = 0l, max = 2L, message = "搜索类型出错!0账号1手机号2用户id") 43 | Integer type 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/HandleCaseParamsUtil.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils 2 | 3 | import com.okay.family.common.bean.testcase.request.CaseDataBean 4 | import com.okay.family.common.enums.RunResult 5 | import com.okay.family.common.exception.UserStatusException 6 | import com.okay.family.fun.frame.SourceCode 7 | import com.okay.family.service.ITestCaseService 8 | import org.slf4j.Logger 9 | import org.slf4j.LoggerFactory 10 | import org.springframework.stereotype.Component 11 | 12 | import javax.annotation.PostConstruct 13 | import java.util.concurrent.ConcurrentHashMap 14 | 15 | @Component 16 | class HandleCaseParamsUtil extends SourceCode { 17 | 18 | private static Logger logger = LoggerFactory.getLogger(HandleCaseParamsUtil.class) 19 | 20 | static ITestCaseService service; 21 | 22 | ITestCaseService caseService 23 | 24 | HandleCaseParamsUtil(ITestCaseService caseService) { 25 | this.caseService = caseService 26 | } 27 | 28 | @PostConstruct 29 | public void init() { 30 | this.service = caseService 31 | } 32 | 33 | 34 | static def handleParams(CaseDataBean bean,ConcurrentHashMap certificates) { 35 | try { 36 | service.handleParams(bean, certificates); 37 | } catch (UserStatusException e) { 38 | logger.error("用户异常!", e); 39 | bean.setAvailable(RunResult.USER_ERROR.getCode()); 40 | } catch (Exception e) { 41 | logger.error("处理用例参数发生错误!", e); 42 | bean.setAvailable(RunResult.UNRUN.getCode()); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/bean/PerformanceResultBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.bean 2 | 3 | 4 | /** 5 | * 性能测试结果集 6 | */ 7 | class PerformanceResultBean extends AbstractBean { 8 | 9 | /** 10 | * 测试用例描述 11 | */ 12 | String mark 13 | 14 | /** 15 | * 开始时间 16 | */ 17 | String startTime 18 | /** 19 | * 结束时间 20 | */ 21 | String endTime 22 | /** 23 | * 表格信息 24 | */ 25 | String table 26 | /** 27 | * 线程数 28 | */ 29 | 30 | int threads 31 | /** 32 | * 总请求次数 33 | */ 34 | 35 | int total 36 | /** 37 | * 平均响应时间 38 | */ 39 | 40 | int rt 41 | /** 42 | * 吞吐量 43 | */ 44 | 45 | double qps 46 | /** 47 | * 错误率 48 | */ 49 | 50 | double errorRate 51 | /** 52 | * 失败率 53 | */ 54 | 55 | double failRate 56 | /** 57 | * 执行总数 58 | */ 59 | 60 | int executeTotal 61 | 62 | PerformanceResultBean(String mark, String startTime, String endTime, int threads, int total, int rt, double qps, double errorRate, double failRate, int executeTotal, String table) { 63 | this.mark = mark 64 | this.startTime = startTime 65 | this.endTime = endTime 66 | this.threads = threads 67 | this.total = total 68 | this.rt = rt 69 | this.qps = qps 70 | this.errorRate = errorRate 71 | this.failRate = failRate 72 | this.executeTotal = executeTotal 73 | this.table = table 74 | //todo:完成记录功能 75 | // MySqlTest.savePerformanceBean(this) 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/casecollect/request/SearchCollectionBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.casecollect.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import com.okay.family.fun.frame.SourceCode 6 | import org.apache.commons.lang3.StringUtils 7 | import org.hibernate.validator.constraints.Range 8 | 9 | import javax.validation.constraints.Min 10 | import javax.validation.constraints.NotNull 11 | 12 | /** 13 | * 搜索用例集 14 | */ 15 | class SearchCollectionBean extends AbstractBean { 16 | 17 | private static final long serialVersionUID = -564894151549848961; 18 | 19 | @NotNull(message = "uid不能为空") 20 | @Min(value = 1L, message = "uid不能为空") 21 | Integer uid 22 | 23 | @NotNull(message = "envId不能为空") 24 | @Range(min = 0L, max = OkayConstant.ENV, message = "环境变量参数错误") 25 | Integer envId 26 | 27 | @NotNull(message = "groupQuery不能为空") 28 | String groupQuery 29 | 30 | @NotNull(message = "pageNum不能为空") 31 | @Min(value = 1L) 32 | Integer pageNum 33 | 34 | @NotNull(message = "pageSize不能为空") 35 | @Range(min = 5L, max = 20L, message = "每页显示数量设置错误") 36 | Integer pageSize 37 | 38 | @NotNull(message = "result不能为空") 39 | @Range(min = 0L, max = 3L, message = "运行结果参数错误") 40 | Integer result 41 | 42 | /** 43 | * 区分用例集名称和ID,1:用例集名称,2:id 44 | */ 45 | Integer type 46 | 47 | def init() { 48 | if (StringUtils.isEmpty(groupQuery)) return 49 | if (SourceCode.isNumber(groupQuery)) type = 2 50 | else type = 1 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/httpclient/GCThread.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame.httpclient; 2 | 3 | 4 | import com.okay.family.fun.config.HttpClientConstant; 5 | import com.okay.family.fun.frame.SourceCode; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | /** 10 | * 从连接池中回收连接的多线程类 11 | */ 12 | public class GCThread extends SourceCode implements Runnable { 13 | 14 | private static Logger logger = LoggerFactory.getLogger(GCThread.class); 15 | 16 | /** 17 | * 资源回收线程 18 | */ 19 | private static volatile Thread gc = init(); 20 | 21 | /** 22 | * 增加了线程状态的判断,同一进程多次运行HTTP请求的压测功能 23 | */ 24 | public synchronized static void starts() { 25 | if (gc.getState() == Thread.State.NEW) gc.start(); 26 | else if (gc.getState() == Thread.State.TERMINATED) gc = init(); 27 | } 28 | 29 | /** 30 | * 初始化方法,获取新的gc线程对象 31 | * 32 | * @return 33 | */ 34 | public static synchronized Thread init() { 35 | FLAG = true; 36 | return new Thread(new GCThread()); 37 | } 38 | 39 | private GCThread() { 40 | } 41 | 42 | /** 43 | * 线程结束标志 44 | */ 45 | private static boolean FLAG = true; 46 | 47 | @Override 48 | public void run() { 49 | logger.info("gc回收线程开始了!"); 50 | while (FLAG) { 51 | sleep(HttpClientConstant.LOOP_INTERVAL); 52 | ClientManage.recyclingConnection(); 53 | } 54 | logger.info("gc回收线程结束了!"); 55 | } 56 | 57 | /** 58 | * 结束线程方法 59 | */ 60 | public static void stop() { 61 | FLAG = false; 62 | } 63 | 64 | 65 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/StartRun.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common; 2 | 3 | import com.okay.family.common.basedata.OkayConstant; 4 | import com.okay.family.fun.frame.SourceCode; 5 | import com.okay.family.service.ICommonService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | 13 | @Component 14 | public class StartRun implements CommandLineRunner { 15 | 16 | private static Logger logger = LoggerFactory.getLogger(StartRun.class); 17 | 18 | ICommonService commonService; 19 | 20 | public StartRun(ICommonService commonService) { 21 | this.commonService = commonService; 22 | } 23 | 24 | @Override 25 | public void run(String... args) { 26 | commonService.clearLock(); 27 | int lock = commonService.lock(OkayConstant.NODE_LOCK); 28 | if (lock == 1) { 29 | OkayConstant.RUN_MARK = new AtomicInteger(SourceCode.getMark() % 100_000_000 + SourceCode.getRandomInt(8) * 100_000_000); 30 | OkayConstant.node = 1; 31 | logger.info("我是节点 {} ----------", OkayConstant.node); 32 | } else { 33 | OkayConstant.node = 2; 34 | logger.info("我是节点 {} ----------", OkayConstant.node); 35 | OkayConstant.RUN_MARK = new AtomicInteger(SourceCode.getMark() % 100_000_000 + 900_000_000); 36 | } 37 | OkayConstant.COLLECTION_MARK = new AtomicInteger(OkayConstant.RUN_MARK.get() / 100); 38 | logger.info("程序初始化运行方法执行完毕……"); 39 | } 40 | 41 | 42 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/request/EditCaseAttributeBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import org.hibernate.validator.constraints.Length 6 | import org.hibernate.validator.constraints.Range 7 | 8 | import javax.validation.constraints.Min 9 | import javax.validation.constraints.NotBlank 10 | import javax.validation.constraints.NotNull 11 | import javax.validation.constraints.Pattern 12 | 13 | /** 14 | * 用例属性编辑 15 | */ 16 | class EditCaseAttributeBean extends AbstractBean { 17 | 18 | private static final long serialVersionUID = -629232822729332L; 19 | 20 | @Min(value = 1L) 21 | Integer id 22 | 23 | @NotNull(message = "uid不能为空") 24 | @Min(value = 1L) 25 | Integer uid 26 | 27 | @NotNull(message = "envId不能为空") 28 | @Range(min = 1L, max = OkayConstant.ENV, message = "环境变量参数错误") 29 | Integer envId 30 | 31 | /** 32 | * 关联服务id 33 | */ 34 | @NotNull(message = "serviceId不能为空") 35 | Integer serviceId 36 | 37 | /** 38 | * 关联服务模块id 39 | */ 40 | @NotNull(message = "moduleId不能为空") 41 | Integer moduleId 42 | 43 | @NotBlank(message = "name不能为空") 44 | @Length(min = 1, max = 60, message = "名字长度错误1-60") 45 | String name 46 | 47 | @NotNull(message = "projectList不能为空") 48 | List projectList 49 | 50 | @NotNull(message = "apiId不能为空") 51 | @Min(value = 1L) 52 | Integer apiId 53 | 54 | @NotNull(message = "type不能为空") 55 | @Pattern(regexp = "add|update|copy", message = "类型错误,应该传:add|update|copy") 56 | String type 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/mapper/TestCaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.mapper; 2 | 3 | import com.okay.family.common.bean.common.DelBean; 4 | import com.okay.family.common.bean.common.ProjectBean; 5 | import com.okay.family.common.bean.common.SimpleBean; 6 | import com.okay.family.common.bean.testcase.CaseRunRecord; 7 | import com.okay.family.common.bean.testcase.request.*; 8 | import com.okay.family.common.bean.testcase.response.*; 9 | 10 | import java.util.List; 11 | 12 | public interface TestCaseMapper { 13 | 14 | int addCase(EditCaseAttributeBean bean); 15 | 16 | int copyCase(EditCaseAttributeBean bean); 17 | 18 | int updateCase(EditCaseAttributeBean bean); 19 | 20 | int updateCaseNoApiId(EditCaseAttributeBean bean); 21 | 22 | int delCase(DelBean bean); 23 | 24 | void addCaseProjectRelation(EditCaseAttributeBean bean); 25 | 26 | void copyCaseProjectRelation(int source, int target); 27 | 28 | void delCaseProjectRelation(DelBean bean); 29 | 30 | void addEditRecord(CaseEditRecord record); 31 | 32 | int updateCaseData(CaseDataBean bean); 33 | 34 | List searchCases(CaseSearchBean bean); 35 | 36 | List searchCaseNoPage(CaseSearchNoPageBean bean); 37 | 38 | TestCaseAttributeBean getAttributeById(int id); 39 | 40 | List getCaseProjectRelation(int id); 41 | 42 | List getCaseEditRecords(CaseEditRecordQueryBean bean); 43 | 44 | CaseDetailBean getCaseDetail(int id); 45 | 46 | void addRunRecord(CaseRunRecord record); 47 | 48 | CaseRunDetailBean getCaseRunRecord(int id); 49 | 50 | int getCaseApiId(int id); 51 | 52 | int syncApi(int caseId); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testuser/request/EditUserBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testuser.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import com.okay.family.fun.config.Constant 6 | import org.hibernate.validator.constraints.Length 7 | import org.hibernate.validator.constraints.Range 8 | 9 | import javax.validation.constraints.Min 10 | import javax.validation.constraints.NotBlank 11 | import javax.validation.constraints.NotNull 12 | import javax.validation.constraints.Pattern 13 | 14 | /** 15 | * 编辑测试用户信息 16 | */ 17 | class EditUserBean extends AbstractBean { 18 | 19 | private static final long serialVersionUID = 548951651651L; 20 | 21 | @Min(value = 1L) 22 | Integer id 23 | 24 | @NotNull(message = "uid不能为空") 25 | @Min(value = 1L, message = "用户ID错误") 26 | Integer uid 27 | 28 | @NotNull(message = "envId不能为空") 29 | @Range(min = 1L, max = OkayConstant.ENV, message = "环境变量错误") 30 | Integer envId 31 | 32 | @NotNull(message = "roleId不能为空") 33 | @Range(min = 1L, max = OkayConstant.ROLE, message = "不支持的用户身份") 34 | Integer roleId 35 | 36 | @NotBlank(message = "user不能为空") 37 | @Length(min = 6, max = 11, message = "用户名长度应为6-11位") 38 | String user 39 | 40 | @NotBlank(message = "type不能为空") 41 | @Pattern(regexp = "add|update|delete", message = "请输入正确的类型:add|update|delete") 42 | String type 43 | 44 | @NotBlank(message = "password不能为空") 45 | @Length(min = 6, max = 20, message = "用户密码长度应为6-20位") 46 | String password 47 | 48 | String phone = Constant.EMPTY 49 | 50 | @Length(min = 0, max = 100, message = "用户描述内容长度错误!1-100") 51 | String des = Constant.EMPTY 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/resources/mapper/CommonMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | family_service_env 7 | 8 | 9 | 10 | qa_request_record 11 | 12 | 13 | 14 | qa_lock 15 | 16 | 17 | 22 | 23 | 28 | 29 | 30 | INSERT INTO 31 | 32 | (api,mark,method,host,size,cost,state,code,requestid) 33 | VALUES 34 | (#{api},#{mark},#{method},#{host},#{size},#{cost},#{status},#{code},#{requestid}) 35 | 36 | 37 | 38 | INSERT INTO 39 | 40 | (id) 41 | VALUES 42 | (#{0}) 43 | 44 | 45 | 46 | delete from 47 | 48 | where id = #{0} 49 | 50 | 51 | 52 | delete from 53 | where create_time #{0} 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/bean/AbstractBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.bean 2 | 3 | import com.alibaba.fastjson.JSON 4 | import com.alibaba.fastjson.JSONObject 5 | import com.okay.family.fun.frame.Save 6 | import com.okay.family.fun.frame.SourceCode 7 | import org.slf4j.Logger 8 | import org.slf4j.LoggerFactory 9 | import org.springframework.beans.BeanUtils 10 | 11 | /** 12 | * bean的基类 13 | */ 14 | abstract class AbstractBean implements Serializable { 15 | 16 | private static final long serialVersionUID = -1595369567071153477L; 17 | 18 | static final Logger logger = LoggerFactory.getLogger(AbstractBean.class) 19 | 20 | /** 21 | * 将bean转化为json,为了进行数据处理和打印 22 | * 23 | * @return 24 | */ 25 | JSONObject toJson() { 26 | JSONObject.parseObject(JSONObject.toJSONString(this)) 27 | } 28 | 29 | /** 30 | * 文本形式保存 31 | */ 32 | def save() { 33 | Save.saveJson(this.toJson(), this.getClass().toString() + SourceCode.getMark()); 34 | } 35 | 36 | /** 37 | * 控制台打印,使用WARN记录,以便查看 38 | */ 39 | def print() { 40 | logger.info(this.getClass().toString() + ":" + this.toString()); 41 | } 42 | 43 | def initFrom(String str) { 44 | return JSONObject.parseObject(str, this.getClass()) 45 | } 46 | 47 | def initFrom(Object str) { 48 | initFrom(JSON.toJSON(str)) 49 | } 50 | 51 | def copyFrom(AbstractBean source) { 52 | BeanUtils.copyProperties(source, this) 53 | } 54 | 55 | def copyTo(AbstractBean target) { 56 | BeanUtils.copyProperties(this, target) 57 | } 58 | 59 | /** 60 | * 这里bean的属性必需是可以访问的,不然会返回空json串 61 | * @return 62 | */ 63 | @Override 64 | String toString() { 65 | JSONObject.toJSONString(this) 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testcase/request/CaseSearchBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testcase.request 2 | 3 | import com.okay.family.common.basedata.OkayConstant 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import com.okay.family.fun.frame.SourceCode 6 | import org.apache.commons.lang3.StringUtils 7 | import org.hibernate.validator.constraints.Range 8 | 9 | import javax.validation.constraints.Min 10 | import javax.validation.constraints.NotNull 11 | 12 | /** 13 | * 用例搜索 14 | */ 15 | class CaseSearchBean extends AbstractBean { 16 | 17 | private static final long serialVersionUID = -869483426556; 18 | 19 | @Min(value = 1L) 20 | Integer uid 21 | 22 | @Range(min = 0L, max = OkayConstant.ENV, message = "环境变量参数错误") 23 | Integer envId 24 | 25 | @Min(value = 1L) 26 | Integer apiId 27 | 28 | @NotNull(message = "isMyself不能为空") 29 | @Range(min = 0L, max = 2L, message = "是否本人参数错误0全部,1本人,2非本人") 30 | Integer isMyself 31 | 32 | @NotNull(message = "isUsed不能为空") 33 | @Range(min = 0L, max = 2L, message = "是否可用参数错误0全部, 1可用,2不可用") 34 | Integer isUsed 35 | 36 | Integer serviceId 37 | 38 | Integer moduleId 39 | 40 | @NotNull(message = "pageNum不能为空") 41 | @Min(value = 1L) 42 | Integer pageNum 43 | 44 | @NotNull(message = "pageSize不能为空") 45 | @Range(min = 5L, max = 10L, message = "单页数值设置错误!") 46 | Integer pageSize 47 | 48 | @Min(value = 0L) 49 | Integer projectId 50 | 51 | @NotNull(message = "testQuery不能为空") 52 | String testQuery 53 | 54 | /** 55 | * 处理搜索类型,1:用例名模糊搜索,2:用例id精确搜索 56 | */ 57 | Integer type 58 | 59 | 60 | def init() { 61 | if (StringUtils.isBlank(testQuery)) return 62 | if (SourceCode.isNumber(testQuery)) type = 2 63 | else type = 1 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/resources/app.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | version="1.0.1"; 3 | 4 | appName="family-qa-dev.jar" 5 | 6 | function start() 7 | { 8 | count=`ps -ef |grep java|grep $appName|wc -l` 9 | if [ $count != 0 ];then 10 | echo "Maybe $appName is running, please check it..." 11 | else 12 | echo "The $appName is starting..." 13 | nohup java -jar ./$appName -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -Xms2G -Xmx2G > /dev/null 2>&1 & 14 | fi 15 | } 16 | 17 | function stop() 18 | { 19 | appId=`ps -ef |grep java|grep $appName|awk '{print $2}'` 20 | if [ -z $appId ];then 21 | echo "Maybe $appName not running, please check it..." 22 | else 23 | echo "The $appName is stopping... $appId" 24 | kill $appId 25 | fi 26 | } 27 | 28 | function restart() 29 | { 30 | 31 | stop 32 | int=1 33 | while [ 1 ]; 34 | do 35 | sleep 1 36 | appId=`ps -ef |grep java|grep $appName|awk '{print $2}'` 37 | # echo $int 38 | if [ -z $appId ]; then 39 | break 40 | fi 41 | echo "waitfor $int second ..." 42 | let "int++" 43 | if [ $int -gt 5 ]; then 44 | echo "超时强制退出" 45 | kill -9 $appId 46 | break 47 | fi 48 | done 49 | 50 | start 51 | } 52 | 53 | function status() 54 | { 55 | appId=`ps -ef |grep java|grep $appName|awk '{print $2}'` 56 | if [ -z $appId ] 57 | then 58 | echo -e "\033[31m Not running \033[0m" 59 | else 60 | echo -e "\033[32m Running [$appId] \033[0m" 61 | fi 62 | } 63 | 64 | 65 | function usage() 66 | { 67 | echo "Usage: $0 {start|stop|restart|status|stop -f}" 68 | echo "Example: $0 start" 69 | exit 1 70 | } 71 | 72 | case $1 in 73 | start) 74 | start;; 75 | 76 | stop) 77 | stop;; 78 | 79 | restart) 80 | restart;; 81 | 82 | status) 83 | status;; 84 | 85 | *) 86 | echo "default restart" 87 | restart;; 88 | esac -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/typehandler/JsonArrayHandler.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.typehandler; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.apache.ibatis.type.BaseTypeHandler; 6 | import org.apache.ibatis.type.JdbcType; 7 | import org.apache.ibatis.type.MappedJdbcTypes; 8 | import org.apache.ibatis.type.MappedTypes; 9 | 10 | import java.sql.CallableStatement; 11 | import java.sql.PreparedStatement; 12 | import java.sql.ResultSet; 13 | import java.sql.SQLException; 14 | 15 | /** 16 | * 处理json数组读写 17 | */ 18 | @MappedTypes(JSONArray.class) 19 | @MappedJdbcTypes(value = JdbcType.VARCHAR) 20 | public class JsonArrayHandler extends BaseTypeHandler { 21 | 22 | @Override 23 | public void setNonNullParameter(PreparedStatement ps, int i, JSONArray parameter, JdbcType jdbcType) throws SQLException { 24 | ps.setString(i, parameter.toString()); 25 | } 26 | 27 | @Override 28 | public JSONArray getNullableResult(ResultSet rs, String columnName) throws SQLException { 29 | String str = rs.getString(columnName); 30 | if (StringUtils.isNoneBlank(str)) { 31 | return JSONArray.parseArray(str); 32 | } 33 | return null; 34 | } 35 | 36 | @Override 37 | public JSONArray getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 38 | String str = rs.getString(columnIndex); 39 | if (StringUtils.isNoneBlank(str)) { 40 | return JSONArray.parseArray(str); 41 | } 42 | return null; 43 | } 44 | 45 | @Override 46 | public JSONArray getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 47 | String str = cs.getString(columnIndex); 48 | if (StringUtils.isNoneBlank(str)) { 49 | return JSONArray.parseArray(str); 50 | } 51 | return null; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/wapper/CommonInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.wapper; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.web.servlet.ModelAndView; 6 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | //@Component("commonInterceptor") 12 | public class CommonInterceptor extends HandlerInterceptorAdapter { 13 | 14 | private static Logger logger = LoggerFactory.getLogger(CommonInterceptor.class); 15 | 16 | @Override 17 | public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o) throws Exception { 18 | try { 19 | RequestWrapper requestWrapper = new RequestWrapper(request); 20 | String url = requestWrapper.getRequestURL().toString(); 21 | String queryArgs = requestWrapper.getQueryString(); 22 | queryArgs = queryArgs == null ? requestWrapper.getBody() : queryArgs; 23 | logger.info("请求url:{},参数:{}", url, queryArgs); 24 | ResponseWrapper responseWrapper = new ResponseWrapper(httpServletResponse); 25 | byte[] content = responseWrapper.getContent(); 26 | String s = new String(content); 27 | logger.error(s); 28 | 29 | return true; 30 | } catch (Exception e) { 31 | logger.error("", e); 32 | } 33 | return false; 34 | } 35 | 36 | @Override 37 | public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { 38 | 39 | } 40 | 41 | @Override 42 | public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/utils/HeapDumper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.utils; 2 | 3 | 4 | import com.okay.family.fun.frame.SourceCode; 5 | import com.sun.management.HotSpotDiagnosticMXBean; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.management.MBeanServer; 10 | import java.lang.management.ManagementFactory; 11 | 12 | /** 13 | * 获取JVM内存转储文件的工具类 14 | */ 15 | public class HeapDumper extends SourceCode { 16 | 17 | private static Logger logger = LoggerFactory.getLogger(HeapDumper.class); 18 | 19 | /** 20 | * 这是HotSpot Diagnostic MBean的名称 21 | */ 22 | private static final String HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"; 23 | 24 | /** 25 | * 用于存储热点诊断MBean的字段 26 | */ 27 | private static volatile HotSpotDiagnosticMXBean hotspotMBean; 28 | 29 | /** 30 | * 下载内存转储文件 31 | * 32 | * @param fileName 文件名,例如:heap.bin,不兼容路径,会在当前目录下生成 33 | * @param live 34 | */ 35 | public static void dumpHeap(String fileName, boolean live) { 36 | initHotspotMBean(); 37 | try { 38 | hotspotMBean.dumpHeap(fileName, live); 39 | } catch (Exception e) { 40 | logger.error("生成内存转储文件失败!", e); 41 | } 42 | } 43 | 44 | /** 45 | * 初始化热点诊断MBean 46 | */ 47 | private static void initHotspotMBean() { 48 | if (hotspotMBean == null) { 49 | synchronized (HeapDumper.class) { 50 | if (hotspotMBean == null) { 51 | try { 52 | MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 53 | hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class); 54 | } catch (Exception e) { 55 | logger.error("初始化mbean失败!", e); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | 62 | 63 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/bean/testuser/TestUserCheckBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.bean.testuser 2 | 3 | import com.okay.family.common.bean.testuser.request.EditUserBean 4 | import com.okay.family.fun.base.bean.AbstractBean 5 | import com.okay.family.fun.config.Constant 6 | 7 | /** 8 | * 用于验证测试用户 9 | */ 10 | class TestUserCheckBean extends AbstractBean { 11 | 12 | private static final long serialVersionUID = -98489156165; 13 | 14 | Integer id 15 | 16 | Integer uid 17 | 18 | Integer envId 19 | 20 | String user 21 | 22 | Integer roleId 23 | 24 | String password 25 | 26 | String phone 27 | 28 | String des 29 | 30 | Integer status 31 | 32 | String certificate = Constant.EMPTY 33 | 34 | String create_time 35 | 36 | def copyFrom(EditUserBean user) { 37 | this.setId(user.getId()); 38 | this.setEnvId(user.getEnvId()); 39 | this.setRoleId(user.getRoleId()); 40 | this.setUser(user.getUser()); 41 | this.setPassword(user.getPassword()); 42 | this.setPhone(user.getPhone()); 43 | this.setUid(user.getUid()); 44 | this.setDes(user.getDes()); 45 | } 46 | 47 | def copyFrom(TestUserCheckBean user) { 48 | this.setId(user.getId()); 49 | this.setEnvId(user.getEnvId()); 50 | this.setRoleId(user.getRoleId()); 51 | this.setUser(user.getUser()); 52 | this.setPassword(user.getPassword()); 53 | this.setPhone(user.getPhone()); 54 | this.setUid(user.getUid()); 55 | this.setDes(user.getDes()); 56 | this.status = user.getStatus() 57 | this.create_time = user.getCreate_time() 58 | this.certificate = user.getCertificate() 59 | } 60 | 61 | /** 62 | * 是否是同一个用户,检查用户关键信息是否更改,用于判断是否要重新登录用户获取最近的凭据 63 | * @param bean 64 | * @return 65 | */ 66 | boolean same(TestUserCheckBean bean) { 67 | this.user == bean.user && this.password == bean.password && this.roleId == bean.roleId; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/xml/XMLUtil2.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils.xml 2 | 3 | import com.okay.family.fun.base.exception.FailException 4 | import com.okay.family.fun.frame.SourceCode 5 | import org.dom4j.* 6 | import org.dom4j.io.SAXReader 7 | import org.slf4j.Logger 8 | import org.slf4j.LoggerFactory 9 | 10 | /** 11 | * 基于dom4j解析xml工具类 12 | */ 13 | class XMLUtil2 extends SourceCode { 14 | 15 | private static Logger logger = LoggerFactory.getLogger(XMLUtil2.class) 16 | 17 | /** 18 | * 解析xml文件 19 | * @param path 绝对路径或者URL 20 | * @return 21 | */ 22 | static List parse(String path) { 23 | SAXReader reader = new SAXReader(); 24 | try { 25 | Document document = reader.read(path.startsWith("http") ? new URL(path) : new File(path)); 26 | Element rootElement = document.getRootElement(); 27 | def iterator = rootElement.elementIterator() 28 | List info = new ArrayList<>() 29 | while (iterator.hasNext()) { 30 | info << parseNode(iterator.next() as Element) 31 | } 32 | return info; 33 | } catch (DocumentException e) { 34 | logger.error("解析文件${path}失败!", e) 35 | } 36 | FailException.fail("解析文件${path}失败!") 37 | } 38 | 39 | /** 40 | * 解析节点信息 41 | * @param e 42 | * @return 43 | */ 44 | static NodeInfo parseNode(Element e) { 45 | if (e.getNodeType() != Node.ELEMENT_NODE) return null; 46 | def info = new NodeInfo() 47 | List attributes = e.attributes(); 48 | List attrs = new ArrayList<>() 49 | attributes.each { 50 | attrs << new Attr(it.name, it.value) 51 | } 52 | info.setAttrs(attrs) 53 | List children = new ArrayList<>() 54 | def iterator = e.elementIterator() 55 | if (iterator.hasNext()) { 56 | children << parseNode(iterator.next() as Element) 57 | } 58 | info.setChildren(children) 59 | return info; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/controller/LiveUpdateController.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.controller; 2 | 3 | 4 | import com.okay.family.common.basedata.FamilyConstant; 5 | import com.okay.family.common.basedata.ServerHost; 6 | import com.okay.family.fun.base.bean.Result; 7 | import com.okay.family.service.ILiveUpdateService; 8 | import com.okay.family.service.ITestCaseService; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import java.util.Map; 15 | 16 | /** 17 | * 热更新接口 18 | */ 19 | @RestController 20 | @RequestMapping(value = "/live") 21 | public class LiveUpdateController { 22 | 23 | ILiveUpdateService service; 24 | 25 | ITestCaseService caseService; 26 | 27 | public LiveUpdateController(ILiveUpdateService service, ITestCaseService caseService) { 28 | this.service = service; 29 | this.caseService = caseService; 30 | } 31 | 32 | @GetMapping(value = "/hosts") 33 | public Result getHosts() { 34 | Map hosts = ServerHost.getHosts(); 35 | return Result.success(hosts); 36 | } 37 | 38 | @GetMapping(value = "/rmhost}") 39 | public Result rmHosts() { 40 | ServerHost.getHosts().clear(); 41 | return Result.success(); 42 | } 43 | 44 | @GetMapping(value = "/hoststime") 45 | public Result getHostsTime() { 46 | Map timeout = ServerHost.getTimeout(); 47 | return Result.success(timeout); 48 | } 49 | 50 | @GetMapping(value = "/case/{caseId}") 51 | public Result updateCaseApiInfo(@PathVariable(value = "caseId", required = true) int caseId) { 52 | caseService.syncApi(caseId); 53 | return Result.success(); 54 | } 55 | 56 | @GetMapping(value = "/output") 57 | public Result editOutput() { 58 | FamilyConstant.OUTPUT = !FamilyConstant.OUTPUT; 59 | return Result.success(); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/thead/RequestThreadTime.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame.thead; 2 | 3 | 4 | import com.okay.family.fun.base.constaint.ThreadLimitTimeCount; 5 | import com.okay.family.fun.base.interfaces.MarkThread; 6 | import com.okay.family.fun.frame.httpclient.FanLibrary; 7 | import com.okay.family.fun.frame.httpclient.FunRequest; 8 | import com.okay.family.fun.frame.httpclient.GCThread; 9 | import org.apache.http.client.methods.HttpRequestBase; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * http请求多线程类 15 | */ 16 | public class RequestThreadTime extends ThreadLimitTimeCount { 17 | 18 | static Logger logger = LoggerFactory.getLogger(RequestThreadTime.class); 19 | 20 | /** 21 | * 请求 22 | */ 23 | public HttpRequestBase request; 24 | 25 | /** 26 | * 单请求多线程多次任务构造方法 27 | * 28 | * @param request 被执行的请求 29 | * @param time 每个线程运行的次数 30 | */ 31 | public RequestThreadTime(HttpRequestBase request, int time) { 32 | super(null, time, null); 33 | this.request = request; 34 | } 35 | 36 | /** 37 | * @param request 被执行的请求 38 | * @param time 执行时间 39 | * @param mark 标记类对象 40 | */ 41 | public RequestThreadTime(HttpRequestBase request, int time, MarkThread mark) { 42 | super(null, time, mark); 43 | this.request = request; 44 | } 45 | 46 | protected RequestThreadTime() { 47 | super(); 48 | } 49 | 50 | @Override 51 | public void before() { 52 | super.before(); 53 | GCThread.starts(); 54 | } 55 | 56 | @Override 57 | protected void doing() throws Exception { 58 | FanLibrary.executeSimlple(request); 59 | } 60 | 61 | 62 | @Override 63 | public RequestThreadTime clone() { 64 | RequestThreadTime threadTime = new RequestThreadTime(); 65 | threadTime.time = this.time; 66 | threadTime.request = FunRequest.cloneRequest(request); 67 | threadTime.mark = mark == null ? null : mark.clone(); 68 | return threadTime; 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/utils/FileUtil.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.utils 2 | 3 | import com.okay.family.fun.frame.SourceCode 4 | import org.slf4j.Logger 5 | import org.slf4j.LoggerFactory 6 | 7 | class FileUtil extends SourceCode { 8 | 9 | private static Logger logger = LoggerFactory.getLogger(FileUtil.class) 10 | 11 | /** 12 | * 拷贝文件 13 | * @param source 14 | * @param target 15 | * @return 16 | */ 17 | static def copy(String source, String target) { 18 | def s = new File(source) 19 | def t = new File(target) 20 | if (s.exists() && s.isFile()) return t.newOutputStream() << s.newInputStream() 21 | output("copy file error!") 22 | } 23 | 24 | /** 25 | * 重命名一个文件 26 | * @param oldPath 27 | * @param newPath 28 | * @return 29 | */ 30 | static def rename(String oldPath, String newPath) { 31 | if (new File(oldPath).renameTo(newPath)) logger.error("rename file error!,old:{},new:{}", oldPath, newPath) 32 | } 33 | 34 | /** 35 | * 从url下载文件 36 | * @param url 37 | * @param name 38 | * @return 39 | */ 40 | static def down(String url, String name) { 41 | new File(name) << new URL(url).openStream() 42 | } 43 | 44 | /** 45 | * 获取文件夹下所有文件的绝对路径的方法,递归,排除了Linux系统的隐藏文件 46 | * 47 | * @param path 48 | * @return 49 | */ 50 | static List getAllFile(String path) { 51 | List list = new ArrayList() 52 | File file = new File(path) 53 | if (!file.exists() || file.isFile()) return list 54 | File[] files = file.listFiles() 55 | int length = files.length 56 | if (length == 0) return list 57 | for (int i in 0..length - 1) { 58 | File file1 = files[i] 59 | if (file1.isDirectory()) { 60 | List allFile = getAllFile(file1.getAbsolutePath()) 61 | list.addAll(allFile) 62 | continue 63 | } 64 | String path1 = file1.getAbsolutePath() 65 | if (path1.contains("/.")) continue 66 | list.add(path1) 67 | } 68 | return list 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/bean/RecordBean.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.bean 2 | 3 | 4 | import org.slf4j.Logger 5 | import org.slf4j.LoggerFactory 6 | 7 | /** 8 | * 测试记录的bean 9 | */ 10 | class RecordBean extends AbstractBean { 11 | 12 | static Logger logger = LoggerFactory.getLogger(RecordBean.class) 13 | 14 | String domain; 15 | 16 | String type; 17 | 18 | String api; 19 | 20 | long expend_time; 21 | 22 | int data_size; 23 | 24 | int status; 25 | 26 | int code; 27 | 28 | String method; 29 | 30 | String local_ip; 31 | 32 | String local_name; 33 | 34 | String create_time; 35 | 36 | public static RecordBean get() { 37 | new RecordBean() 38 | } 39 | 40 | RecordBean setDomain(String domain) { 41 | this.domain = domain 42 | this 43 | } 44 | 45 | RecordBean setType(String type) { 46 | this.type = type 47 | this 48 | } 49 | 50 | RecordBean setApi(String api) { 51 | this.api = api 52 | this 53 | } 54 | 55 | RecordBean setExpend_time(long expend_time) { 56 | this.expend_time = expend_time 57 | this 58 | } 59 | 60 | RecordBean setData_size(int data_size) { 61 | this.data_size = data_size 62 | this 63 | } 64 | 65 | RecordBean setStatus(int status) { 66 | this.status = status 67 | this 68 | } 69 | 70 | RecordBean setCode(int code) { 71 | this.code = code 72 | this 73 | } 74 | 75 | RecordBean setMethod(String method) { 76 | this.method = method 77 | this 78 | } 79 | 80 | RecordBean setLocal_ip(String local_ip) { 81 | this.local_ip = local_ip 82 | this 83 | } 84 | 85 | RecordBean setLocal_name(String local_name) { 86 | this.local_name = local_name 87 | this 88 | } 89 | 90 | RecordBean setCreate_time(String create_time) { 91 | this.create_time = create_time 92 | this 93 | } 94 | 95 | @Override 96 | def print() { 97 | logger.info "接口:{},响应时间{}", api, expend_time 98 | } 99 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/thead/HeaderMark.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame.thead; 2 | 3 | 4 | import com.okay.family.fun.base.constaint.ThreadBase; 5 | import com.okay.family.fun.base.exception.ParamException; 6 | import com.okay.family.fun.base.interfaces.MarkRequest; 7 | import com.okay.family.fun.frame.SourceCode; 8 | import org.apache.http.client.methods.HttpRequestBase; 9 | 10 | import java.io.Serializable; 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | 13 | public class HeaderMark extends SourceCode implements MarkRequest, Cloneable, Serializable { 14 | 15 | private static final long serialVersionUID = -1595942567071153477L; 16 | 17 | public static AtomicInteger threadName = new AtomicInteger(getRandomIntRange(1000, 9000)); 18 | 19 | String headerName; 20 | 21 | int i; 22 | 23 | int num = getRandomIntRange(100, 999) * 1000; 24 | 25 | @Override 26 | public String mark(ThreadBase threadBase) { 27 | if (threadBase instanceof RequestThreadTime) { 28 | RequestThreadTime req = (RequestThreadTime) threadBase; 29 | return mark(req.request); 30 | } else if (threadBase instanceof RequestThreadTimes) { 31 | RequestThreadTimes req = (RequestThreadTimes) threadBase; 32 | return mark(req.request); 33 | } else { 34 | ParamException.fail(threadBase.getClass().toString()); 35 | } 36 | return EMPTY; 37 | } 38 | 39 | /** 40 | * 标记请求 41 | * 42 | * @param base 43 | * @return 44 | */ 45 | @Override 46 | public String mark(HttpRequestBase base) { 47 | base.removeHeaders(headerName); 48 | String value = 8 + EMPTY + i + num++; 49 | base.addHeader(headerName, value); 50 | return value; 51 | } 52 | 53 | @Override 54 | public HeaderMark clone() { 55 | return new HeaderMark(headerName); 56 | } 57 | 58 | public HeaderMark(String headerName) { 59 | this.headerName = headerName; 60 | this.i = threadName.getAndIncrement(); 61 | } 62 | 63 | public HeaderMark() { 64 | 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/constaint/FixedQpsThread.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.constaint; 2 | 3 | import com.okay.family.fun.base.interfaces.MarkThread; 4 | import com.okay.family.fun.config.HttpClientConstant; 5 | import com.okay.family.fun.frame.execute.FixedQpsConcurrent; 6 | import com.okay.family.fun.utils.Time; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public abstract class FixedQpsThread extends ThreadBase { 11 | 12 | private static Logger logger = LoggerFactory.getLogger(FixedQpsThread.class); 13 | 14 | public int qps; 15 | 16 | /** 17 | * 根据属性isTimesMode判断,次数或者时间(单位ms) 18 | */ 19 | public int limit; 20 | 21 | public boolean isTimesMode; 22 | 23 | public FixedQpsThread(T t, int limit, int qps, MarkThread markThread, boolean isTimesMode) { 24 | this.limit = limit; 25 | this.qps = qps; 26 | this.mark = markThread; 27 | this.t = t; 28 | this.isTimesMode = isTimesMode; 29 | } 30 | 31 | 32 | protected FixedQpsThread() { 33 | super(); 34 | } 35 | 36 | @Override 37 | public void run() { 38 | try { 39 | before(); 40 | threadmark = this.mark == null ? EMPTY : this.mark.mark(this); 41 | FixedQpsConcurrent.executeTimes.getAndIncrement(); 42 | long s = Time.getTimeStamp(); 43 | doing(); 44 | long e = Time.getTimeStamp(); 45 | long diff = e - s; 46 | FixedQpsConcurrent.allTimes.add(diff); 47 | if (diff > HttpClientConstant.MAX_ACCEPT_TIME) 48 | FixedQpsConcurrent.marks.add(diff + CONNECTOR + threadmark); 49 | } catch (Exception e) { 50 | FixedQpsConcurrent.errorTimes.getAndIncrement(); 51 | logger.warn("执行任务失败!,标记:{}", threadmark, e); 52 | } finally { 53 | after(); 54 | } 55 | } 56 | 57 | @Override 58 | public void before() { 59 | 60 | } 61 | 62 | /** 63 | * 子类必需实现改方法,不然调用deepclone方法会报错 64 | * 65 | * @return 66 | */ 67 | public abstract FixedQpsThread clone(); 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/thead/RequestThreadTimes.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame.thead; 2 | 3 | 4 | import com.okay.family.fun.base.constaint.ThreadLimitTimesCount; 5 | import com.okay.family.fun.base.interfaces.MarkThread; 6 | import com.okay.family.fun.frame.httpclient.FanLibrary; 7 | import com.okay.family.fun.frame.httpclient.FunRequest; 8 | import com.okay.family.fun.frame.httpclient.GCThread; 9 | import org.apache.http.client.methods.HttpRequestBase; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * http请求多线程类 15 | */ 16 | public class RequestThreadTimes extends ThreadLimitTimesCount { 17 | 18 | static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class); 19 | 20 | /** 21 | * 请求 22 | */ 23 | public HttpRequestBase request; 24 | 25 | /** 26 | * 单请求多线程多次任务构造方法 27 | * 28 | * @param request 被执行的请求 29 | * @param times 每个线程运行的次数 30 | */ 31 | public RequestThreadTimes(HttpRequestBase request, int times) { 32 | super(null, times, null); 33 | this.request = request; 34 | } 35 | 36 | /** 37 | * 应对对每个请求进行标记的情况 38 | * 39 | * @param request 40 | * @param times 41 | * @param mark 42 | */ 43 | public RequestThreadTimes(HttpRequestBase request, int times, MarkThread mark) { 44 | super(null, times, mark); 45 | this.request = request; 46 | } 47 | 48 | protected RequestThreadTimes() { 49 | super(); 50 | } 51 | 52 | @Override 53 | public void before() { 54 | super.before(); 55 | GCThread.starts(); 56 | } 57 | 58 | /** 59 | * @throws Exception 60 | */ 61 | @Override 62 | protected void doing() throws Exception { 63 | FanLibrary.executeSimlple(request); 64 | } 65 | 66 | @Override 67 | public RequestThreadTimes clone() { 68 | RequestThreadTimes threadTimes = new RequestThreadTimes(); 69 | threadTimes.times = this.times; 70 | threadTimes.request = FunRequest.cloneRequest(request); 71 | threadTimes.mark = mark == null ? null : mark.clone(); 72 | return threadTimes; 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/mapper/CaseCollectionMapper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.mapper; 2 | 3 | import com.okay.family.common.bean.casecollect.request.*; 4 | import com.okay.family.common.bean.casecollect.response.CollectionCaseInfoBean; 5 | import com.okay.family.common.bean.casecollect.response.CollectionRunResultDetailBean; 6 | import com.okay.family.common.bean.casecollect.response.ListCaseBean; 7 | import com.okay.family.common.bean.casecollect.response.ListCollectionBean; 8 | import com.okay.family.common.bean.common.DelBean; 9 | import com.okay.family.common.bean.common.SimpleBean; 10 | import com.okay.family.common.bean.testcase.request.CaseDataBean; 11 | import com.okay.family.common.bean.casecollect.request.DelCollectionBean; 12 | import com.okay.family.common.bean.testcase.response.ListCaseRunResultBean; 13 | 14 | import java.util.List; 15 | 16 | public interface CaseCollectionMapper { 17 | 18 | int addCollection(AddCollectionBean bean); 19 | 20 | void addCollectionCaseRelation(AddCollectionBean beans); 21 | 22 | void addEditRcord(CaseCollectionEditRecord record); 23 | 24 | int delCollection(DelCollectionBean bean); 25 | 26 | void delCollectionCaseRelation(DelCollectionBean bean); 27 | 28 | int editCollection(CollectionEditBean bean); 29 | 30 | int shareCollection(DelCollectionBean bean); 31 | 32 | int delCaseFromCollection(DelCaseCollectionRelationBean bean); 33 | 34 | List getCases(int collectionId, int uid); 35 | 36 | List getCaseIds(int collectionId); 37 | 38 | List getCasesDeatil(RunCollectionBean bean); 39 | 40 | CollectionCaseInfoBean getCollectionInfo(CollectionCaseInfoBean bean); 41 | 42 | void addCollectionRunRecord(CollectionRunResultRecord record); 43 | 44 | void updateCollectionStatus(int id, int status); 45 | 46 | List findCollecions(SearchCollectionBean bean); 47 | 48 | List searchCollectionNoPage(SearchCollectionNoPageBean bean); 49 | 50 | List getRecords(DelBean bean); 51 | 52 | List getCaseRunRecord(int runId); 53 | 54 | CollectionRunResultDetailBean getCollectionRunDetail(int runId); 55 | 56 | void delAllCaseCollectionRelation(int id); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/ITestCaseService.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.github.pagehelper.PageInfo; 5 | import com.okay.family.common.bean.common.DelBean; 6 | import com.okay.family.common.bean.common.SimpleBean; 7 | import com.okay.family.common.bean.testcase.CaseRunRecord; 8 | import com.okay.family.common.bean.testcase.request.*; 9 | import com.okay.family.common.bean.testcase.response.*; 10 | 11 | import java.util.List; 12 | import java.util.concurrent.ConcurrentHashMap; 13 | import java.util.concurrent.CountDownLatch; 14 | 15 | public interface ITestCaseService { 16 | 17 | 18 | int addCase(EditCaseAttributeBean bean); 19 | 20 | int copyCase(EditCaseAttributeBean bean); 21 | 22 | int updateCase(EditCaseAttributeBean bean); 23 | 24 | int delCase(DelBean bean); 25 | 26 | void addCaseProjectRelation(EditCaseAttributeBean bean); 27 | 28 | void delCaseProjectRelation(DelBean bean); 29 | 30 | void updateCaseProjectRelation(EditCaseAttributeBean bean); 31 | 32 | void copyCaseProjectRelation(int source, int target); 33 | 34 | void addEditRecord(CaseEditRecord record); 35 | 36 | int updateCaseData(CaseDataBean bean); 37 | 38 | List searchCaseNoPage(CaseSearchNoPageBean bean); 39 | 40 | PageInfo searchCases(CaseSearchBean bean); 41 | 42 | TestCaseAttributeBean getAttributeById(int id); 43 | 44 | void getAttributeById(TestCaseAttributeBean bean, CountDownLatch countDownLatch); 45 | 46 | void getCaseProjectRelation(TestCaseAttributeBean bean, CountDownLatch countDownLatch); 47 | 48 | PageInfo getCaseEditRecords(CaseEditRecordQueryBean bean); 49 | 50 | CaseDetailBean getCaseDetail(int id); 51 | 52 | CaseRunRecord runCaseData(CaseDataBean bean); 53 | 54 | void addRunRecord(CaseRunRecord runRecord); 55 | 56 | void handleParams(JSONObject params, ConcurrentHashMap map); 57 | 58 | void handleParams(JSONObject params); 59 | 60 | void handleParams(CaseDataBean bean); 61 | 62 | void handleParams(CaseDataBean bean, ConcurrentHashMap map); 63 | 64 | void delAllCaseCollectionRelation(int id); 65 | 66 | CaseRunDetailBean getCaseRunRecord(int id); 67 | 68 | void syncApi(int caseId); 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/threadpool/CaseRunThread.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.threadpool; 2 | 3 | import com.okay.family.common.basedata.OkayConstant; 4 | import com.okay.family.common.bean.testcase.CaseRunRecord; 5 | import com.okay.family.common.bean.testcase.request.CaseDataBean; 6 | import com.okay.family.common.enums.CaseAvailableStatus; 7 | import com.okay.family.common.enums.RunResult; 8 | import com.okay.family.utils.RunCaseUtil; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.util.concurrent.CountDownLatch; 13 | 14 | public class CaseRunThread implements Runnable { 15 | 16 | private static Logger logger = LoggerFactory.getLogger(CaseRunThread.class); 17 | 18 | int envId; 19 | 20 | CaseDataBean bean; 21 | 22 | CaseRunRecord record; 23 | 24 | CountDownLatch countDownLatch; 25 | 26 | public CaseRunRecord getRecord() { 27 | return record; 28 | } 29 | 30 | private CaseRunThread() { 31 | 32 | } 33 | 34 | public CaseRunThread(CaseDataBean bean, CountDownLatch countDownLatch, int runId, int envId) { 35 | this.bean = bean; 36 | this.envId = envId; 37 | this.countDownLatch = countDownLatch; 38 | this.record = new CaseRunRecord(); 39 | record.setRunId(runId); 40 | record.setUid(bean.getUid()); 41 | record.setParams(bean.getParams()); 42 | record.setCaseId(bean.getId()); 43 | record.setMark(OkayConstant.RUN_MARK.getAndIncrement()); 44 | bean.getHeaders().put(OkayConstant.MARK_HEADER, record.getMark()); 45 | record.setHeaders(bean.getHeaders()); 46 | } 47 | 48 | @Override 49 | public void run() { 50 | try { 51 | if (bean.getAvailable() == RunResult.USER_ERROR.getCode()) { 52 | record.fail(RunResult.USER_ERROR, bean); 53 | } else if (bean.getEnvId() != envId || bean.getAvailable() != CaseAvailableStatus.OK.getCode()) { 54 | record.fail(RunResult.UNRUN, bean); 55 | } else { 56 | RunCaseUtil.run(bean, record); 57 | } 58 | } catch (Exception e) { 59 | logger.warn("用例运行出错,ID:" + bean.getId(), e); 60 | record.fail(RunResult.UNRUN, bean); 61 | } finally { 62 | countDownLatch.countDown(); 63 | } 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/wapper/ResponseWrapper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.wapper; 2 | 3 | import javax.servlet.ServletOutputStream; 4 | import javax.servlet.WriteListener; 5 | import javax.servlet.http.HttpServletResponse; 6 | import javax.servlet.http.HttpServletResponseWrapper; 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.IOException; 9 | import java.io.PrintWriter; 10 | 11 | public class ResponseWrapper extends HttpServletResponseWrapper { 12 | private ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 13 | 14 | private PrintWriter printWriter = new PrintWriter(outputStream); 15 | 16 | public ResponseWrapper(HttpServletResponse response) { 17 | super(response); 18 | } 19 | 20 | @Override 21 | public ServletOutputStream getOutputStream() throws IOException { 22 | return new ServletOutputStream() { 23 | @Override 24 | public boolean isReady() { 25 | return false; 26 | } 27 | 28 | @Override 29 | public void setWriteListener(WriteListener writeListener) { 30 | 31 | } 32 | 33 | @Override 34 | public void write(int b) throws IOException { 35 | outputStream.write(b); 36 | } 37 | 38 | @Override 39 | public void write(byte[] b) throws IOException { 40 | outputStream.write(b); 41 | } 42 | 43 | @Override 44 | public void write(byte[] b, int off, int len) throws IOException { 45 | outputStream.write(b, off, len); 46 | } 47 | 48 | @Override 49 | public void flush() throws IOException { 50 | outputStream.flush(); 51 | } 52 | }; 53 | } 54 | 55 | @Override 56 | public PrintWriter getWriter() throws IOException { 57 | return printWriter; 58 | } 59 | 60 | public void flush(){ 61 | try { 62 | printWriter.flush(); 63 | printWriter.close(); 64 | outputStream.flush(); 65 | outputStream.close(); 66 | } catch (IOException e) { 67 | e.printStackTrace(); 68 | } 69 | } 70 | 71 | public byte[] getContent() { 72 | flush(); 73 | return outputStream.toByteArray(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/utils/Join.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.utils; 2 | 3 | 4 | import com.okay.family.fun.frame.SourceCode; 5 | import org.apache.commons.lang3.ArrayUtils; 6 | import org.apache.commons.lang3.StringUtils; 7 | 8 | public class Join extends SourceCode { 9 | 10 | /** 11 | * 把字符串每个字符用分隔器连接起来 12 | * 13 | * @param text 14 | * @param separator 15 | * @return 16 | */ 17 | public static String join(String text, String separator) { 18 | return StringUtils.join(ArrayUtils.toObject(text.toCharArray()), separator); 19 | } 20 | 21 | /** 22 | * 把字符串每个字符用分隔器连接起来 23 | * 24 | * @param text 25 | * @param separator 26 | * @return 27 | */ 28 | public static String join(String text, String separator, String prefix, String suffix) { 29 | return prefix + join(text, separator) + suffix; 30 | } 31 | 32 | /** 33 | * 把Iterable用分隔器连接起来 34 | * 35 | * @param iterable 36 | * @param separator 37 | * @param prefix 38 | * @param suffix 39 | * @return 40 | */ 41 | public static String join(Iterable iterable, String separator, String prefix, String suffix) { 42 | return prefix + join(iterable, separator) + suffix; 43 | // return list.stream().map(x -> x.toString()).collect(Collectors.joining(separator, prefix, suffix)).toString(); 44 | } 45 | 46 | /** 47 | * 把Iterable用分隔器连接起来,没有前后缀 48 | * 49 | * @param iterable 50 | * @param separator 51 | * @return 52 | */ 53 | public static String join(Iterable iterable, String separator) { 54 | return StringUtils.join(iterable, separator); 55 | } 56 | 57 | 58 | /** 59 | * 把数组添加用间隔符连接 60 | * 61 | * @param objects 62 | * @param separator 63 | * @param prefix 前缀 64 | * @param suffix 后缀 65 | * @return 66 | */ 67 | public static String join(Object[] objects, String separator, String prefix, String suffix) { 68 | return prefix + join(objects, separator) + suffix; 69 | } 70 | 71 | /** 72 | * 把数组添加用间隔符连接 73 | * 74 | * @param objects 75 | * @param separator 间隔 76 | * @return 77 | */ 78 | public static String join(Object[] objects, String separator) { 79 | return StringUtils.join(objects, separator); 80 | } 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/VerifyResponseUtil.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils 2 | 3 | import com.alibaba.fastjson.JSONObject 4 | import com.okay.family.common.basedata.OkayConstant 5 | import com.okay.family.common.bean.testcase.CaseVerifyBean 6 | import com.okay.family.fun.frame.SourceCode 7 | import org.apache.commons.lang3.StringUtils 8 | import org.slf4j.Logger 9 | import org.slf4j.LoggerFactory 10 | 11 | import java.util.regex.PatternSyntaxException 12 | 13 | class VerifyResponseUtil extends SourceCode { 14 | 15 | private static final Logger logger = LoggerFactory.getLogger(VerifyResponseUtil.class) 16 | 17 | /** 18 | * 校验响应结果 19 | * @param response 20 | * @param beans 21 | * @return 22 | */ 23 | static boolean verify(JSONObject response, List beans) { 24 | String content = response.getIntValue(RESPONSE_CODE) == TEST_ERROR_CODE ? response.getString(RESPOINSE_CONTENT) : response.toString() 25 | if (StringUtils.isEmpty(content)) { 26 | beans.each {it.setResult("响应错误无法验证false")} 27 | return false 28 | } 29 | beans.each { 30 | def key = it.getText() 31 | def desc = StringUtils.isBlank(it.getDes()) ? OkayConstant.DEFAULT_VERIFY_DEC : it.getDes() 32 | if (key.contains("code")) { 33 | String str = "\"" + key + "\":" + it.getValue() 34 | it.setResult(desc + OkayConstant.RUN_RESULT_TEXT + content.contains(str)) 35 | } else if (key.contains("regex")) { 36 | try { 37 | it.setResult(desc + OkayConstant.RUN_RESULT_TEXT + (content ==~ it.getValue())) 38 | } catch (PatternSyntaxException e) { 39 | it.setResult(desc + OkayConstant.RUN_RESULT_TEXT + OkayConstant.PATTEN_ERROR_TEXT + false) 40 | } 41 | } else { 42 | it.setResult(desc + OkayConstant.RUN_RESULT_TEXT + false) 43 | } 44 | } 45 | beans.every { 46 | it.getResult().endsWith("true") 47 | } 48 | } 49 | 50 | /** 51 | * 获取code通用方法 52 | * @param response 53 | * @return 54 | */ 55 | static int getCode(JSONObject response) { 56 | def str = response.toString() 57 | def matcher = str =~ /code":\d+/ 58 | matcher.find() ? changeStringToInt(matcher[0] - "code\":") : TEST_ERROR_CODE 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/execute/ThreadPoolUtil.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame.execute; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * Java线程池Demo 7 | */ 8 | class ThreadPoolUtil { 9 | 10 | 11 | /** 12 | * 重建可变线程池 13 | * corePoolSize:核心池的大小,这个参数跟后面讲述的线程池的实现原理有非常大的关系。在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; 14 | * maximumPoolSize:线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程; 15 | * keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0; 16 | * unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性: 17 | * workQueue:一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择:ArrayBlockingQueue;LinkedBlockingQueue; SynchronousQueue; 18 | *   ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。 19 | * threadFactory:线程工厂,主要用来创建线程; 20 | * handler:表示当拒绝处理任务时的策略,有以下四种取值: 21 | * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 22 | * ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 23 | * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) 24 | * ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 25 | * 26 | * @param core 核心线程数 27 | * @param max 最大线程数 28 | * @param liveTime 空闲时间 29 | * @return 30 | */ 31 | static ThreadPoolExecutor createPool(int core = 5, int max = 20, int liveTime = 5) { 32 | return new ThreadPoolExecutor(core, max, liveTime, TimeUnit.SECONDS, new LinkedBlockingDeque(1000)); 33 | 34 | } 35 | 36 | /** 37 | * 定长的线程池 38 | * 39 | * @param size 40 | * @return 41 | */ 42 | static ExecutorService createFixedPool(int size = 10) { 43 | return Executors.newFixedThreadPool(size); 44 | } 45 | 46 | /** 47 | * 缓存线程池,无限长度 48 | * 49 | * @return 50 | */ 51 | static ExecutorService createCachePool() { 52 | return Executors.newCachedThreadPool(); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/controller/TestUserController.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.controller; 2 | 3 | import com.github.pagehelper.PageInfo; 4 | import com.okay.family.common.basedata.OkayMethod; 5 | import com.okay.family.common.bean.common.DelBean; 6 | import com.okay.family.common.bean.testuser.request.EditUserBean; 7 | import com.okay.family.common.bean.testuser.request.SearchUserBean; 8 | import com.okay.family.common.bean.testuser.response.TestUserBean; 9 | import com.okay.family.common.code.CommonCode; 10 | import com.okay.family.common.code.TestUserCode; 11 | import com.okay.family.fun.base.bean.Result; 12 | import com.okay.family.fun.frame.SourceCode; 13 | import com.okay.family.service.ITestUserService; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.web.bind.annotation.*; 17 | 18 | import javax.validation.Valid; 19 | 20 | @RestController 21 | @RequestMapping(value = "/user") 22 | public class TestUserController { 23 | 24 | public static Logger logger = LoggerFactory.getLogger(TestUserController.class); 25 | 26 | ITestUserService testUserService; 27 | 28 | public TestUserController(ITestUserService testUserService) { 29 | this.testUserService = testUserService; 30 | } 31 | 32 | @GetMapping(value = "/get") 33 | public Result findUsers(@Valid SearchUserBean bean) { 34 | PageInfo users = testUserService.findUsers(bean); 35 | return Result.success(users); 36 | } 37 | 38 | @PostMapping(value = "/edit") 39 | public Result editUser(@RequestBody @Valid EditUserBean bean) { 40 | if (bean.getType().equalsIgnoreCase("add")) { 41 | int add = testUserService.addUser(bean); 42 | return add > 0 ? Result.success(SourceCode.getJson("id=" + add)) : Result.fail(TestUserCode.ADD_USER_FAIL); 43 | } else if (bean.getType().equalsIgnoreCase("update")) { 44 | int i = testUserService.updateUser(bean); 45 | return i == 1 ? Result.success(OkayMethod.getSimpleResult(bean)) : Result.fail(OkayMethod.getSimpleResult(bean)); 46 | } 47 | return Result.fail(CommonCode.PARAMS_ERROR); 48 | } 49 | 50 | @PostMapping(value = "/del") 51 | public Result delUser(@RequestBody @Valid DelBean bean) { 52 | int i = testUserService.delUesr(bean); 53 | return i == 0 ? Result.fail(TestUserCode.DEL_USER_FAIL) : Result.success(); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/ICaseCollectionService.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service; 2 | 3 | import com.github.pagehelper.PageInfo; 4 | import com.okay.family.common.bean.casecollect.request.*; 5 | import com.okay.family.common.bean.casecollect.response.CollectionCaseInfoBean; 6 | import com.okay.family.common.bean.casecollect.response.CollectionRunResultDetailBean; 7 | import com.okay.family.common.bean.casecollect.response.CollectionRunSimpleResutl; 8 | import com.okay.family.common.bean.casecollect.response.ListCollectionBean; 9 | import com.okay.family.common.bean.common.DelBean; 10 | import com.okay.family.common.bean.common.SimpleBean; 11 | import com.okay.family.common.bean.testcase.request.CaseDataBean; 12 | import com.okay.family.common.bean.casecollect.request.DelCollectionBean; 13 | 14 | import java.util.List; 15 | import java.util.concurrent.CountDownLatch; 16 | 17 | public interface ICaseCollectionService { 18 | 19 | int addCollection(AddCollectionBean beans); 20 | 21 | void addCollectionCaseRelation(AddCollectionBean bean); 22 | 23 | void addCollectionEditRecord(CaseCollectionEditRecord record); 24 | 25 | int editCollection(CollectionEditBean bean); 26 | 27 | int shareCollection(DelCollectionBean bean); 28 | 29 | int delCollection(DelCollectionBean bean); 30 | 31 | void delCollectionCaseRelation(DelCollectionBean bean); 32 | 33 | int delCaseFromCollection(DelCaseCollectionRelationBean bean); 34 | 35 | CollectionCaseInfoBean getCases(int collectionId, int uid); 36 | 37 | void getCollectionInfo(CollectionCaseInfoBean bean, CountDownLatch countDownLatch); 38 | 39 | CollectionRunSimpleResutl runCollection(RunCollectionBean bean); 40 | 41 | void addCollectionRunRecord(CollectionRunResultRecord record); 42 | 43 | List getCasesDeatil(RunCollectionBean bean); 44 | 45 | void updateCollectionStatus(int id, int status); 46 | 47 | PageInfo findCollecions(SearchCollectionBean bean); 48 | 49 | List searchCollectionNoPage(SearchCollectionNoPageBean bean); 50 | 51 | List getRecords(DelBean bean); 52 | 53 | CollectionRunResultDetailBean getCollectionRunDetail(int runId); 54 | 55 | void getCaseRunRecord(CollectionRunResultDetailBean bean, CountDownLatch countDownLatch); 56 | 57 | void getCollectionRunResult(CollectionRunResultDetailBean bean, CountDownLatch countDownLatch); 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/typehandler/JsonHandler.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.typehandler; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.apache.ibatis.type.BaseTypeHandler; 6 | import org.apache.ibatis.type.JdbcType; 7 | import org.apache.ibatis.type.MappedJdbcTypes; 8 | import org.apache.ibatis.type.MappedTypes; 9 | 10 | import java.sql.CallableStatement; 11 | import java.sql.PreparedStatement; 12 | import java.sql.ResultSet; 13 | import java.sql.SQLException; 14 | 15 | /** 16 | * @description 用以mysql中json格式的字段,进行转换的自定义转换器,转换为实体类的JSONObject属性 17 | */ 18 | @MappedTypes(JSONObject.class) 19 | @MappedJdbcTypes(JdbcType.VARCHAR) 20 | public class JsonHandler extends BaseTypeHandler { 21 | 22 | /** 23 | * 设置非空参数 24 | * 25 | * @param ps 26 | * @param i 27 | * @param jdbcType 28 | * @throws SQLException 29 | */ 30 | @Override 31 | public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException { 32 | ps.setString(i, String.valueOf(parameter.toJSONString())); 33 | } 34 | 35 | /** 36 | * 根据列名,获取可以为空的结果 37 | * 38 | * @param rs 39 | * @param columnName 40 | * @return 41 | * @throws SQLException 42 | */ 43 | @Override 44 | public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException { 45 | String str = rs.getString(columnName); 46 | if (StringUtils.isNoneBlank(str)) { 47 | return JSONObject.parseObject(str); 48 | } 49 | return null; 50 | } 51 | 52 | /** 53 | * 根据列索引,获取可以为空的结果 54 | * 55 | * @param rs 56 | * @param columnIndex 57 | * @return 58 | * @throws SQLException 59 | */ 60 | @Override 61 | public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 62 | String str = rs.getString(columnIndex); 63 | if (StringUtils.isNoneBlank(str)) { 64 | return JSONObject.parseObject(str); 65 | } 66 | return null; 67 | } 68 | 69 | @Override 70 | public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 71 | String str = cs.getString(columnIndex); 72 | if (StringUtils.isNoneBlank(str)) { 73 | return JSONObject.parseObject(str); 74 | } 75 | return null; 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/bean/Result.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.bean 2 | 3 | import com.alibaba.fastjson.JSONArray 4 | import com.alibaba.fastjson.JSONObject 5 | import com.github.pagehelper.PageInfo 6 | import com.okay.family.common.code.CommonCode 7 | import com.okay.family.fun.base.interfaces.ReturnCode 8 | 9 | /** 10 | * 通用的返回体 11 | * 配合moco框架使用 12 | */ 13 | class Result extends AbstractBean { 14 | 15 | /** 16 | * code码 17 | */ 18 | int code 19 | 20 | String msg 21 | 22 | /** 23 | * 返回信息 24 | */ 25 | T data 26 | 27 | private Result(int code, String msg, T data) { 28 | this.code = code 29 | this.msg = msg 30 | this.data = data 31 | } 32 | 33 | private Result(int code, String msg) { 34 | this(code, msg, new JSONObject(0)) 35 | } 36 | 37 | private Result(ReturnCode errorCode) { 38 | this(errorCode.getCode(), errorCode.getDesc()) 39 | } 40 | 41 | private Result() { 42 | } 43 | 44 | /** 45 | * 返回成功响应内容 46 | * @param data 47 | * @return 48 | */ 49 | static Result success(T data) { 50 | new Result(0, CommonCode.SUCCESS.getDesc(), data) 51 | } 52 | 53 | static Result success(PageInfo data) { 54 | JSONObject res = new JSONObject(); 55 | res.put("pageNum", data.getPageNum()); 56 | res.put("list", data.getList()); 57 | res.put("total", data.getTotal()); 58 | new Result(CommonCode.SUCCESS.getCode(), CommonCode.SUCCESS.getDesc(), res) 59 | } 60 | 61 | static Result success() { 62 | new Result(CommonCode.SUCCESS) 63 | } 64 | 65 | static Result success(JSONArray listData) { 66 | success([list: listData] as JSONObject) 67 | } 68 | 69 | static Result success(List listData) { 70 | success([list: listData] as JSONObject) 71 | } 72 | 73 | 74 | /** 75 | * 返回通用失败的响应内容 76 | * @param data 77 | * @return 78 | */ 79 | static Result fail(T data) { 80 | fail(CommonCode.FAIL,data.toString()) 81 | } 82 | 83 | static Result fail(ReturnCode errorCode, String data) { 84 | new Result(errorCode.getCode(), errorCode.getDesc(), data) 85 | } 86 | static Result fail(ReturnCode errorCode) { 87 | new Result(errorCode) 88 | } 89 | static Result fail(int code, String msg) { 90 | new Result(code, msg) 91 | } 92 | static Result fail() { 93 | new Result(CommonCode.FAIL) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/typehandler/ListIntegerHandler.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.typehandler; 2 | 3 | import com.okay.family.fun.config.Constant; 4 | import com.okay.family.fun.utils.Join; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.apache.ibatis.type.BaseTypeHandler; 7 | import org.apache.ibatis.type.JdbcType; 8 | import org.apache.ibatis.type.MappedJdbcTypes; 9 | import org.apache.ibatis.type.MappedTypes; 10 | 11 | import java.sql.CallableStatement; 12 | import java.sql.PreparedStatement; 13 | import java.sql.ResultSet; 14 | import java.sql.SQLException; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | import static com.okay.family.fun.frame.SourceCode.changeStringToInt; 20 | 21 | @MappedTypes(List.class) 22 | @MappedJdbcTypes(JdbcType.VARCHAR) 23 | public class ListIntegerHandler extends BaseTypeHandler> { 24 | 25 | @Override 26 | public void setNonNullParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) throws SQLException { 27 | ps.setString(i, Join.join(parameter, Constant.COMMA)); 28 | } 29 | 30 | @Override 31 | public List getNullableResult(ResultSet rs, String columnName) throws SQLException { 32 | String str = rs.getString(columnName); 33 | if (StringUtils.isNoneBlank(str)) { 34 | String[] split = str.split(Constant.COMMA); 35 | return Arrays.asList(split).stream().map(x -> changeStringToInt(x)).collect(Collectors.toList()); 36 | } 37 | return null; 38 | } 39 | 40 | @Override 41 | public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 42 | String str = rs.getString(columnIndex); 43 | if (StringUtils.isNoneBlank(str)) { 44 | String[] split = str.split(Constant.COMMA); 45 | return Arrays.asList(split).stream().map(x -> changeStringToInt(x)).collect(Collectors.toList()); 46 | } 47 | return null; 48 | } 49 | 50 | @Override 51 | public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 52 | String str = cs.getString(columnIndex); 53 | if (StringUtils.isNoneBlank(str)) { 54 | String[] split = str.split(Constant.COMMA); 55 | return Arrays.asList(split).stream().map(x -> changeStringToInt(x)).collect(Collectors.toList()); 56 | } 57 | return null; 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/service/impl/PubDataServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.service.impl; 2 | 3 | import com.okay.family.common.bean.common.DelBean; 4 | import com.okay.family.common.bean.pubdata.request.EditPubBean; 5 | import com.okay.family.common.bean.pubdata.request.SavePubDataBean; 6 | import com.okay.family.common.bean.pubdata.response.PubDataBean; 7 | import com.okay.family.mapper.PubDataMapper; 8 | import com.okay.family.service.IPubDataService; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | @Service 14 | public class PubDataServiceImpl implements IPubDataService { 15 | 16 | 17 | PubDataMapper pubDataMapper; 18 | 19 | public PubDataServiceImpl(PubDataMapper pubDataMapper) { 20 | this.pubDataMapper = pubDataMapper; 21 | } 22 | 23 | /** 24 | * 获取所有公共数据 25 | * 26 | * @param uid 27 | * @return 28 | */ 29 | @Override 30 | public List getAllDatas(int uid) { 31 | List allDatas = pubDataMapper.getAllDatas(uid); 32 | return allDatas; 33 | } 34 | 35 | /** 36 | * 获取某一环境下的公共数据,用于编写测试用例时候用 37 | * 38 | * @param uid 39 | * @param envId 40 | * @return 41 | */ 42 | @Override 43 | public List getDatasByEnv(int uid, int envId) { 44 | List datasByEnv = pubDataMapper.getDatasByEnv(uid, envId); 45 | return datasByEnv; 46 | } 47 | 48 | /** 49 | * 添加公共数据 50 | * 51 | * @param bean 52 | * @return 53 | */ 54 | @Override 55 | public int addData(EditPubBean bean) { 56 | int add = pubDataMapper.add(bean); 57 | return bean.getId(); 58 | } 59 | 60 | /** 61 | * 删除公共数据 62 | * 63 | * @param bean 64 | * @return 65 | */ 66 | @Override 67 | public int delData(DelBean bean) { 68 | int i = pubDataMapper.delData(bean); 69 | return i; 70 | } 71 | 72 | /** 73 | * 更新公共数据属性 74 | * 75 | * @param bean 76 | * @return 77 | */ 78 | @Override 79 | public int updateDataAttribute(EditPubBean bean) { 80 | int i = pubDataMapper.updateDataAttribute(bean); 81 | return i; 82 | } 83 | 84 | /** 85 | * 保存公共数据内容 86 | * 87 | * @param bean 88 | * @return 89 | */ 90 | @Override 91 | public int saveData(SavePubDataBean bean) { 92 | int i = pubDataMapper.saveData(bean); 93 | return i; 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/resources/mapper/PubDataMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | qa_pub_data 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 31 | 32 | 33 | UPDATE 34 | 35 | SET 36 | name=#{name} 37 | WHERE id=#{id} and uid = #{uid} 38 | 39 | 40 | 41 | 42 | UPDATE 43 | 44 | SET 45 | list=#{list,jdbcType=OTHER,typeHandler=com.okay.family.common.typehandler.ListPubDetailHandler} 46 | WHERE id=#{id} AND uid=#{uid} 47 | 48 | 49 | 50 | 51 | INSERT INTO 52 | 53 | (uid,name,envId,list) 54 | VALUES 55 | (#{uid},#{name},#{envId},'') 56 | 57 | 58 | 59 | delete from 60 | 61 | where id = #{id} and uid = #{uid} 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/controller/PubDataController.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.controller; 2 | 3 | import com.okay.family.common.bean.common.DelBean; 4 | import com.okay.family.common.bean.pubdata.request.EditPubBean; 5 | import com.okay.family.common.bean.pubdata.request.SavePubDataBean; 6 | import com.okay.family.common.bean.pubdata.response.PubDataBean; 7 | import com.okay.family.common.code.CommonCode; 8 | import com.okay.family.common.code.PubDataCode; 9 | import com.okay.family.fun.base.bean.Result; 10 | import com.okay.family.fun.frame.SourceCode; 11 | import com.okay.family.service.IPubDataService; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import javax.validation.Valid; 17 | import java.util.List; 18 | 19 | @RestController 20 | @RequestMapping(value = "/pubdata") 21 | public class PubDataController { 22 | 23 | private static Logger logger = LoggerFactory.getLogger(PubDataController.class); 24 | 25 | 26 | IPubDataService pubDataService; 27 | 28 | public PubDataController(IPubDataService pubDataService) { 29 | this.pubDataService = pubDataService; 30 | } 31 | 32 | @GetMapping(value = "/get") 33 | public Result getDatas(@RequestParam(value = "uid", required = true) int uid, 34 | @RequestParam(value = "envId", required = true) int envId) { 35 | List datas = pubDataService.getDatasByEnv(uid, envId); 36 | return Result.success(datas); 37 | } 38 | 39 | @PostMapping(value = "/edit") 40 | public Result delData(@RequestBody @Valid EditPubBean bean) { 41 | if (bean.getType().equalsIgnoreCase("update")) { 42 | int i = pubDataService.updateDataAttribute(bean); 43 | return Result.success(); 44 | } else if (bean.getType().equalsIgnoreCase("add")) { 45 | int i = pubDataService.addData(bean); 46 | return i > 0 ? Result.success(SourceCode.getJson("id=" + i)) : Result.fail(PubDataCode.ADD_FAIL); 47 | } 48 | logger.warn("未验证的参数:{}", bean.toString()); 49 | return Result.fail(CommonCode.PARAMS_ERROR); 50 | } 51 | 52 | @PostMapping(value = "/del") 53 | public Result delData(@RequestBody @Valid DelBean bean) { 54 | int i = pubDataService.delData(bean); 55 | return Result.success(); 56 | } 57 | 58 | @PostMapping(value = "/save") 59 | public Result saveData(@RequestBody @Valid SavePubDataBean bean) { 60 | int i = pubDataService.saveData(bean); 61 | return Result.success(); 62 | 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/xml/XMLUtil.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils.xml 2 | 3 | import com.okay.family.fun.base.exception.FailException 4 | import com.okay.family.fun.frame.SourceCode 5 | import org.slf4j.Logger 6 | import org.slf4j.LoggerFactory 7 | import org.w3c.dom.Document 8 | import org.w3c.dom.NamedNodeMap 9 | import org.w3c.dom.Node 10 | import org.w3c.dom.NodeList 11 | import org.xml.sax.SAXException 12 | 13 | import javax.xml.parsers.DocumentBuilder 14 | import javax.xml.parsers.DocumentBuilderFactory 15 | import javax.xml.parsers.ParserConfigurationException 16 | 17 | /** 18 | * 基于dom解析xml文件工具类 19 | */ 20 | class XMLUtil extends SourceCode { 21 | 22 | private static Logger logger = LoggerFactory.getLogger(XMLUtil.class) 23 | 24 | /** 25 | * 解析某个节点(根节点)信息 26 | * @param path 绝对路径或者URL 27 | * @param root 28 | * @return 29 | */ 30 | static List parseRoot(String path, String root) { 31 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance() 32 | try { 33 | DocumentBuilder db = dbf.newDocumentBuilder() 34 | Document document = db.parse(path.startsWith("http") ? new URI(path) : new File(path)) 35 | NodeList nodeList = document.getElementsByTagName(root) 36 | return range(nodeList.getLength()).mapToObj {x -> parseNode(nodeList.item(x))}.collect() as List 37 | } catch (ParserConfigurationException e) { 38 | logger.error("解析配置错误!", e) 39 | } catch (IOException e) { 40 | logger.error("IO错误!", e) 41 | } catch (SAXException e) { 42 | logger.error("SAX错误!", e) 43 | } 44 | FailException.fail("解析文件:${path}中${root}节点出错!") 45 | } 46 | 47 | /** 48 | * 解析某个节点信息 49 | * @param node 50 | * @return 51 | */ 52 | static NodeInfo parseNode(Node node) { 53 | if (node.getNodeType() != Node.ELEMENT_NODE) return null 54 | NodeInfo nodeInfo = new NodeInfo() 55 | NamedNodeMap attrs = node.getAttributes() 56 | List nodeAttr = new ArrayList<>() 57 | range(attrs.getLength()).each { 58 | Node attr = attrs.item(it) 59 | nodeAttr << new Attr(attr.getNodeName(), attr.getNodeValue()) 60 | } 61 | nodeInfo.attrs = nodeAttr 62 | NodeList childNodes = node.getChildNodes() 63 | List children = new ArrayList<>() 64 | range(childNodes.getLength()).each {children.add(parseNode(childNodes.item(it)))} 65 | nodeInfo.children = children.findAll {it != null} 66 | return nodeInfo 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | %level %class:%line %X{id} %msg%n 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | 21 | ${LOG_HOME}/${SEVER_NAME}-info.log 22 | 23 | %d{yyyy-MM-dd HH:mm:ss} %level %class:%line %X{id} [%thread] %msg%n 24 | UTF-8 25 | 26 | 27 | 28 | info 29 | 30 | 31 | 32 | ${LOG_HOME}/${SEVER_NAME}-info.log.%d{yyyy-MM-dd} 33 | 34 | 10 35 | 36 | 37 | 38 | 39 | 40 | ${LOG_HOME}/${SEVER_NAME}-error.log 41 | 42 | %d{yyyy-MM-dd HH:mm:ss} %level %class:%line %X{id} [%thread] %msg%n 43 | UTF-8 44 | 45 | 46 | 47 | warn 48 | 50 | 51 | 52 | 53 | ${LOG_HOME}/${SEVER_NAME}-error.log.%d{yyyy-MM-dd} 54 | 55 | 10 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/typehandler/ListPubDetailHandler.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.typehandler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.okay.family.common.basedata.OkayConstant; 5 | import com.okay.family.common.bean.pubdata.PubDataDetailBean; 6 | import com.okay.family.fun.config.Constant; 7 | import com.okay.family.fun.utils.Join; 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.apache.ibatis.type.BaseTypeHandler; 10 | import org.apache.ibatis.type.JdbcType; 11 | import org.apache.ibatis.type.MappedJdbcTypes; 12 | import org.apache.ibatis.type.MappedTypes; 13 | 14 | import java.sql.CallableStatement; 15 | import java.sql.PreparedStatement; 16 | import java.sql.ResultSet; 17 | import java.sql.SQLException; 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | 23 | @MappedTypes(List.class) 24 | @MappedJdbcTypes(JdbcType.VARCHAR) 25 | public class ListPubDetailHandler extends BaseTypeHandler> { 26 | 27 | @Override 28 | public void setNonNullParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) throws SQLException { 29 | ps.setString(i, Join.join(parameter, OkayConstant.MYSQL_SEPARATE)); 30 | } 31 | 32 | @Override 33 | public List getNullableResult(ResultSet rs, String columnName) throws SQLException { 34 | String str = rs.getString(columnName); 35 | if (StringUtils.isNoneBlank(str)) { 36 | List beans = Arrays.asList(str.split(OkayConstant.MYSQL_SEPARATE)); 37 | return beans.stream().map(x -> JSON.parseObject(x, PubDataDetailBean.class)).collect(Collectors.toList()); 38 | } 39 | return new ArrayList<>(); 40 | } 41 | 42 | @Override 43 | public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 44 | String str = rs.getString(columnIndex); 45 | if (StringUtils.isNoneBlank(str)) { 46 | List beans = Arrays.asList(str.split(Constant.PART)); 47 | return beans.stream().map(x -> JSON.parseObject(x, PubDataDetailBean.class)).collect(Collectors.toList()); 48 | } 49 | return new ArrayList<>(); 50 | } 51 | 52 | @Override 53 | public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 54 | String str = cs.getString(columnIndex); 55 | if (StringUtils.isNoneBlank(str)) { 56 | List beans = Arrays.asList(str.split(Constant.PART)); 57 | return beans.stream().map(x -> JSON.parseObject(x, PubDataDetailBean.class)).collect(Collectors.toList()); 58 | } 59 | return new ArrayList<>(); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/utils/Regex.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.utils; 2 | 3 | 4 | import com.okay.family.fun.base.exception.ParamException; 5 | import com.okay.family.fun.frame.SourceCode; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | /** 16 | * 正则验证的封装 17 | */ 18 | public class Regex extends SourceCode { 19 | 20 | private static Logger logger = LoggerFactory.getLogger(Regex.class); 21 | 22 | /** 23 | * 正则校验文本是否匹配 24 | * 25 | * @param text 需要匹配的文本 26 | * @param regex 正则表达式 27 | * @return 28 | */ 29 | public static boolean isRegex(String text, String regex) { 30 | if (StringUtils.isAnyBlank(text, regex)) ParamException.fail("正则参数错误!"); 31 | return Pattern.compile(regex).matcher(text).find(); 32 | } 33 | 34 | /** 35 | * 正则校验文本是否完全匹配,不包含其他杂项,相当于加上了^和$ 36 | * 37 | * @param text 需要匹配的文本 38 | * @param regex 正则表达式 39 | * @return 40 | */ 41 | public static boolean isMatch(String text, String regex) { 42 | if (StringUtils.isAnyBlank(text, regex)) ParamException.fail("正则参数错误!"); 43 | return Pattern.compile(regex).matcher(text).matches(); 44 | } 45 | 46 | /** 47 | * 返回所有匹配项 48 | * 49 | * @param text 需要匹配的文本 50 | * @param regex 正则表达式 51 | * @return 52 | */ 53 | public static List regexAll(String text, String regex) { 54 | if (StringUtils.isAnyBlank(text, regex)) ParamException.fail("正则参数错误!"); 55 | List result = new ArrayList<>(); 56 | Matcher matcher = Pattern.compile(regex).matcher(text); 57 | while (matcher.find()) { 58 | result.add(matcher.group()); 59 | } 60 | return result; 61 | } 62 | 63 | /** 64 | * 获取匹配项,不包含文字信息,会删除regex的内容 65 | *

不保证完全正确

66 | * 67 | * @param text 68 | * @param regex 69 | * @return 70 | */ 71 | public static String getRegex(String text, String regex) { 72 | if (StringUtils.isAnyBlank(text, regex)) ParamException.fail("正则参数错误!"); 73 | String result = EMPTY; 74 | try { 75 | result = regexAll(text, regex).get(0); 76 | String[] split = regex.split("(\\.|\\+|\\*|\\?)"); 77 | for (int i = 0; i < split.length; i++) { 78 | String s1 = split[i]; 79 | if (!s1.isEmpty()) 80 | result = result.replaceAll(s1, EMPTY); 81 | } 82 | } catch (Exception e) { 83 | logger.warn("获取匹配对象失败!", e); 84 | } finally { 85 | return result; 86 | } 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/typehandler/ListCaseVerifyBeanHandler.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.typehandler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.okay.family.common.basedata.OkayConstant; 5 | import com.okay.family.common.bean.testcase.CaseVerifyBean; 6 | import com.okay.family.fun.config.Constant; 7 | import com.okay.family.fun.utils.Join; 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.apache.ibatis.type.BaseTypeHandler; 10 | import org.apache.ibatis.type.JdbcType; 11 | import org.apache.ibatis.type.MappedJdbcTypes; 12 | import org.apache.ibatis.type.MappedTypes; 13 | 14 | import java.sql.CallableStatement; 15 | import java.sql.PreparedStatement; 16 | import java.sql.ResultSet; 17 | import java.sql.SQLException; 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | 23 | /** 24 | * 处理用例详情的读写 25 | */ 26 | @MappedTypes(List.class) 27 | @MappedJdbcTypes(JdbcType.VARCHAR) 28 | public class ListCaseVerifyBeanHandler extends BaseTypeHandler> { 29 | 30 | @Override 31 | public void setNonNullParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) throws SQLException { 32 | ps.setString(i, Join.join(parameter, OkayConstant.MYSQL_SEPARATE)); 33 | } 34 | 35 | @Override 36 | public List getNullableResult(ResultSet rs, String columnName) throws SQLException { 37 | String str = rs.getString(columnName); 38 | if (StringUtils.isNoneBlank(str)) { 39 | List beans = Arrays.asList(str.split(OkayConstant.MYSQL_SEPARATE)); 40 | return beans.stream().map(x -> JSON.parseObject(x, CaseVerifyBean.class)).collect(Collectors.toList()); 41 | } 42 | return new ArrayList<>(); 43 | } 44 | 45 | @Override 46 | public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 47 | String str = rs.getString(columnIndex); 48 | if (StringUtils.isNoneBlank(str)) { 49 | List beans = Arrays.asList(str.split(Constant.PART)); 50 | return beans.stream().map(x -> JSON.parseObject(x, CaseVerifyBean.class)).collect(Collectors.toList()); 51 | } 52 | return new ArrayList<>(); 53 | } 54 | 55 | @Override 56 | public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 57 | String str = cs.getString(columnIndex); 58 | if (StringUtils.isNoneBlank(str)) { 59 | List beans = Arrays.asList(str.split(Constant.PART)); 60 | return beans.stream().map(x -> JSON.parseObject(x, CaseVerifyBean.class)).collect(Collectors.toList()); 61 | } 62 | return new ArrayList<>(); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/controller/CommonDataController.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.controller; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.okay.family.common.basedata.OkayConstant; 6 | import com.okay.family.common.enums.*; 7 | import com.okay.family.fun.base.bean.Result; 8 | import com.okay.family.service.ICommonService; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import static com.okay.family.fun.frame.SourceCode.getJson; 14 | 15 | @RestController 16 | @RequestMapping(value = "/common") 17 | public class CommonDataController { 18 | 19 | ICommonService service; 20 | 21 | public CommonDataController(ICommonService service) { 22 | this.service = service; 23 | } 24 | 25 | /** 26 | * 用户身份 27 | * 28 | * @return 29 | */ 30 | @GetMapping(value = "/roles") 31 | public Result getIdentity() { 32 | JSONArray all = Identity.getAll(); 33 | return Result.success(all); 34 | } 35 | 36 | 37 | /** 38 | * 填写规则 39 | * 40 | * @return 41 | */ 42 | @GetMapping(value = "/rule") 43 | public Result getRule() { 44 | JSONObject json = getJson("text=" + OkayConstant.RULE); 45 | return Result.success(json); 46 | } 47 | 48 | /** 49 | * 用户状态 50 | * 51 | * @return 52 | */ 53 | @GetMapping(value = "/userstate") 54 | public Result getUserState() { 55 | JSONArray all = UserState.getAll(); 56 | return Result.success(all); 57 | } 58 | 59 | 60 | /** 61 | * 用例集状态 62 | * 63 | * @return 64 | */ 65 | @GetMapping(value = "/collectstate") 66 | public Result getCollectState() { 67 | JSONArray all = CollectionStatus.getAll(); 68 | return Result.success(all); 69 | } 70 | 71 | 72 | /** 73 | * 用例运行状态 74 | * 75 | * @return 76 | */ 77 | @GetMapping(value = "/runresult") 78 | public Result getRunResult() { 79 | JSONArray all = RunResult.getAll(); 80 | return Result.success(all); 81 | } 82 | 83 | /** 84 | * 用例可用性状态 85 | * 86 | * @return 87 | */ 88 | @GetMapping(value = "/caseavailable") 89 | public Result getCaseAvailable() { 90 | JSONArray all = CaseAvailableStatus.getAll(); 91 | return Result.success(all); 92 | } 93 | 94 | @GetMapping(value = "/lock") 95 | public Result lock() { 96 | int lock = service.lock(1L); 97 | return Result.success(lock); 98 | } 99 | 100 | @GetMapping(value = "/unlock") 101 | public Result unlock() { 102 | int unlock = service.unlock(1L); 103 | return Result.success(unlock); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/typehandler/ResultArrayHandler.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.typehandler; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.okay.family.fun.frame.SourceCode; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.apache.ibatis.type.BaseTypeHandler; 7 | import org.apache.ibatis.type.JdbcType; 8 | import org.apache.ibatis.type.MappedJdbcTypes; 9 | import org.apache.ibatis.type.MappedTypes; 10 | 11 | import java.sql.CallableStatement; 12 | import java.sql.PreparedStatement; 13 | import java.sql.ResultSet; 14 | import java.sql.SQLException; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | 18 | /** 19 | * 从数据库里面读取的map运行结果转化成json格式 20 | */ 21 | @MappedTypes(JSONArray.class) 22 | @MappedJdbcTypes(JdbcType.VARCHAR) 23 | public class ResultArrayHandler extends BaseTypeHandler { 24 | 25 | @Override 26 | public void setNonNullParameter(PreparedStatement ps, int i, JSONArray parameter, JdbcType jdbcType) throws SQLException { 27 | ps.setString(i, String.valueOf(parameter.toJSONString())); 28 | } 29 | 30 | @Override 31 | public JSONArray getNullableResult(ResultSet rs, String columnName) throws SQLException { 32 | String str = rs.getString(columnName); 33 | if (StringUtils.isNoneBlank(str)) { 34 | JSONArray result = new JSONArray(); 35 | List asList = Arrays.asList(str.split(";")); 36 | asList.stream().forEach(x -> { 37 | String[] split = x.split("=", 2); 38 | result.add(SourceCode.getJson("text=" + split[0], "amount=" + split[1])); 39 | }); 40 | return result; 41 | } 42 | return null; 43 | } 44 | 45 | @Override 46 | public JSONArray getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 47 | String str = rs.getString(columnIndex); 48 | if (StringUtils.isNoneBlank(str)) { 49 | JSONArray result = new JSONArray(); 50 | List asList = Arrays.asList(str.split(";")); 51 | asList.stream().forEach(x -> { 52 | String[] split = x.split("=", 2); 53 | result.add(SourceCode.getJson("text=" + split[0], "amount=" + split[1])); 54 | }); 55 | return result; 56 | } 57 | return null; 58 | } 59 | 60 | @Override 61 | public JSONArray getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 62 | String str = cs.getString(columnIndex); 63 | if (StringUtils.isNoneBlank(str)) { 64 | JSONArray result = new JSONArray(); 65 | List asList = Arrays.asList(str.split(";")); 66 | asList.stream().forEach(x -> { 67 | String[] split = x.split("=", 2); 68 | result.add(SourceCode.getJson("text=" + split[0], "amount=" + split[1])); 69 | }); 70 | return result; 71 | } 72 | return null; 73 | 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/wapper/WrappingFilter.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.wapper; 2 | 3 | 4 | import com.okay.family.common.basedata.FamilyConstant; 5 | import com.okay.family.common.basedata.OkayConstant; 6 | import com.okay.family.fun.config.Constant; 7 | import com.okay.family.fun.frame.Output; 8 | import com.okay.family.fun.utils.DecodeEncode; 9 | import com.okay.family.fun.utils.Time; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.slf4j.MDC; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.servlet.*; 16 | import javax.servlet.annotation.WebFilter; 17 | import javax.servlet.http.HttpServletRequest; 18 | import javax.servlet.http.HttpServletResponse; 19 | import java.io.IOException; 20 | import java.lang.invoke.MethodHandles; 21 | 22 | 23 | @Component 24 | @WebFilter(urlPatterns = "/*", filterName = "wrappingFilter") 25 | public class WrappingFilter implements Filter { 26 | 27 | private static Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); 28 | 29 | public void init(FilterConfig config) throws ServletException { 30 | } 31 | 32 | public void destroy() { 33 | } 34 | 35 | @Override 36 | public void doFilter(ServletRequest request, ServletResponse response, 37 | FilterChain chain) throws IOException, ServletException { 38 | 39 | HttpServletRequest req = (HttpServletRequest) request; 40 | HttpServletResponse resp = (HttpServletResponse) response; 41 | ResponseWrapper responseWrapper = new ResponseWrapper(resp); 42 | RequestWrapper requestWrapper = new RequestWrapper(req); 43 | String url = requestWrapper.getRequestURI(); 44 | String queryArgs = requestWrapper.getQueryString(); 45 | queryArgs = queryArgs == null ? DecodeEncode.unicodeToString(requestWrapper.getBody()) : queryArgs; 46 | 47 | String requestId = req.getHeader(OkayConstant.REQUEST_ID); 48 | // if(StringUtils.isBlank(requestId)){ 49 | // resp.getWriter().write(Result.fail(CommonCode.REQUESTID_ERROR).toString()); 50 | // resp.flushBuffer(); 51 | // return; 52 | // } 53 | MDC.put("id", requestId); 54 | long start = Time.getTimeStamp(); 55 | chain.doFilter(requestWrapper == null ? request : requestWrapper, responseWrapper); 56 | long end = Time.getTimeStamp(); 57 | byte[] bytes = responseWrapper.getContent(); 58 | String respContent = new String(bytes, Constant.UTF_8); 59 | if (!url.startsWith("/ws")) { 60 | logger.info("请求:{},耗时:{} ms,参数:{},响应:{}", url, end - start, queryArgs, respContent); 61 | try { 62 | if (FamilyConstant.OUTPUT) Output.showStr(queryArgs); 63 | if (FamilyConstant.OUTPUT) Output.showStr(respContent); 64 | } catch (Exception e) { 65 | 66 | } 67 | response.getOutputStream().write(respContent.getBytes(Constant.UTF_8)); 68 | } 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/middle/common/CasCredential.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.middle.common 2 | 3 | import com.alibaba.fastjson.JSONObject 4 | import com.okay.family.common.basedata.OkayConstant 5 | import com.okay.family.fun.config.HttpClientConstant 6 | import com.okay.family.fun.frame.httpclient.FanLibrary 7 | import com.okay.family.fun.utils.Regex 8 | import org.apache.http.client.methods.HttpGet 9 | import org.slf4j.Logger 10 | import org.slf4j.LoggerFactory 11 | 12 | /** 13 | * cas服务验证类,主要解决web端登录验证功能 14 | */ 15 | class CasCredential extends FanLibrary { 16 | 17 | static final String OR = "/" 18 | 19 | private static Logger logger = LoggerFactory.getLogger(CasCredential.class) 20 | 21 | public static Map hosts = new HashMap((int) OkayConstant.ENV) { 22 | 23 | private static final long serialVersionUID = 62275063453465844L; 24 | 25 | { 26 | put(OkayConstant.HOTFIX, MiddleConstant.CAS_HOTFIX); 27 | put(OkayConstant.DEV, MiddleConstant.CAS_DEV); 28 | put(OkayConstant.STRESS, MiddleConstant.CAS_STRESS); 29 | put(OkayConstant.ONLINE, MiddleConstant.CAS_ONLINE) 30 | } 31 | }; 32 | 33 | 34 | /** 35 | * 校验值,随机一次性,从login返回页面中获取 36 | */ 37 | String lt 38 | /** 39 | * 校验值,随机一次性,从login返回页面中获取,正常值长度在4000+,低于4000请检查请求连接是否传入了回调服务的地址 40 | */ 41 | String execution 42 | 43 | /** 44 | * 从cas服务的login页面获取到令牌对,此处正则暂时可用,二期会修改表单提交 45 | */ 46 | CasCredential(String host, int envId) { 47 | def get = getHttpGet(hosts.get(envId) + (host.endsWith(OR) ? host : host + OR)) 48 | def response = getHttpResponse(get) 49 | def string = response.getString("content") 50 | this.lt = Regex.getRegex(string, "") 51 | this.execution = Regex.getRegex(string, "") 52 | // logger.info("cas服务登录host:{},lt:{},execution:{}", host, lt, execution) 53 | } 54 | 55 | /** 56 | * 各个服务端参数一致,由各个服务自己把参数拼好之后传过来,之后在去cas服务拿到令牌对 57 | * @param host 服务的host地址,回调由各个服务自己完成,二次验证也是,此处的host不做兼容,有cascredential做处理 58 | * @param params 拼好的参数 59 | * @return 60 | */ 61 | static JSONObject getTGC(String host, JSONObject params, int envId) { 62 | def credential = new CasCredential(host,envId) 63 | params.put("lt", credential.getLt()); 64 | params.put("execution", credential.getExecution()) 65 | params.put("_eventId", "submit"); 66 | def post = FanLibrary.getHttpPost(hosts.get(envId) + (host.endsWith(OR) ? host : host + OR), params) 67 | FanLibrary.getHttpResponse(post) 68 | } 69 | 70 | /** 71 | * 通过用户st连接获取cookie 72 | * @param url 73 | * @return 74 | */ 75 | public static JSONObject verifyST(String url) { 76 | HttpGet location = FanLibrary.getHttpGet(url); 77 | JSONObject httpResponse = FanLibrary.getHttpResponse(location); 78 | httpResponse.getJSONObject(HttpClientConstant.COOKIE) as JSONObject 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/constaint/ThreadBase.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.constaint; 2 | 3 | 4 | import com.okay.family.fun.base.interfaces.MarkThread; 5 | import com.okay.family.fun.frame.SourceCode; 6 | 7 | import java.util.List; 8 | import java.util.concurrent.CountDownLatch; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * 多线程任务基类,可单独使用 13 | * 14 | * @param 必需实现Serializable 15 | */ 16 | public abstract class ThreadBase extends SourceCode implements Runnable { 17 | 18 | /** 19 | * 线程的名字 20 | */ 21 | public String threadName; 22 | 23 | /** 24 | * 线程标记对象,用户标记请求或者单次执行任务的 25 | */ 26 | public String threadmark; 27 | 28 | /** 29 | * 错误数 30 | */ 31 | public int errorNum; 32 | 33 | /** 34 | * 执行数,一般与响应时间记录数量相同 35 | */ 36 | public int executeNum; 37 | 38 | /** 39 | * 计数锁 40 | *

41 | * 会在concurrent类里面根据线程数自动设定 42 | *

43 | */ 44 | protected CountDownLatch countDownLatch; 45 | 46 | /** 47 | * 标记对象 48 | */ 49 | public MarkThread mark; 50 | 51 | /** 52 | * 用于设置访问资源,用于闭包中无法访问包外实例对象的情况 53 | */ 54 | public T t; 55 | 56 | protected ThreadBase() { 57 | } 58 | 59 | /** 60 | * groovy无法直接访问t,所以写了这个方法,如果报错可以忽略,直接运行,兴许可以成功的 61 | * 62 | * @return 63 | */ 64 | public String getTString() { 65 | return t.toString(); 66 | } 67 | 68 | /** 69 | * 运行待测方法的之前的准备 70 | */ 71 | protected abstract void before(); 72 | 73 | /** 74 | * 待测方法 75 | * 76 | * @throws Exception 抛出异常后记录错误次数,一般在性能测试的时候重置重试控制器不再重试 77 | */ 78 | protected abstract void doing() throws Exception; 79 | 80 | /** 81 | * 运行待测方法后的处理 82 | */ 83 | protected void after() { 84 | if (countDownLatch != null) 85 | countDownLatch.countDown(); 86 | } 87 | 88 | /** 89 | * 设置计数器 90 | * 91 | * @param countDownLatch 92 | */ 93 | public void setCountDownLatch(CountDownLatch countDownLatch) { 94 | this.countDownLatch = countDownLatch; 95 | } 96 | 97 | /** 98 | * 拷贝对象方法,用于统计单一对象多线程调用时候的请求数和成功数,对于的复杂情况,需要将T类型也重写clone方法 99 | * 100 | *

101 | * 此处若具体实现类而非虚拟类建议自己写clone方法 102 | *

103 | * 104 | * @return 105 | */ 106 | @Override 107 | public ThreadBase clone() { 108 | return deepClone(this); 109 | } 110 | 111 | /** 112 | * 线程任务是否需要提前关闭,默认返回false 113 | *

114 | * 一般用于单线程错误率过高的情况 115 | *

116 | * 117 | * @return 118 | */ 119 | public boolean status() { 120 | return false; 121 | } 122 | 123 | /** 124 | * Groovy乘法调用方法 125 | * 126 | * @param num 127 | * @return 128 | */ 129 | public List multiply(int num) { 130 | return range(num).mapToObj(x -> this.clone()).collect(Collectors.toList()); 131 | } 132 | 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/utils/RunCaseUtil.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.utils; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.okay.family.common.bean.testcase.CaseRunRecord; 5 | import com.okay.family.common.bean.testcase.request.CaseDataBean; 6 | import com.okay.family.common.enums.RequestType; 7 | import com.okay.family.common.enums.RunResult; 8 | import com.okay.family.fun.frame.SourceCode; 9 | import com.okay.family.fun.frame.httpclient.FunRequest; 10 | import com.okay.family.service.ICommonService; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.annotation.PostConstruct; 16 | 17 | @Component 18 | public class RunCaseUtil extends SourceCode { 19 | 20 | static Logger logger = LoggerFactory.getLogger(RunCaseUtil.class); 21 | 22 | static ICommonService service; 23 | 24 | ICommonService commonService; 25 | 26 | public RunCaseUtil(ICommonService service) { 27 | this.commonService = service; 28 | } 29 | 30 | @PostConstruct 31 | public void init() { 32 | service = this.commonService; 33 | } 34 | 35 | 36 | public static void run(CaseDataBean bean, CaseRunRecord record) { 37 | if (!bean.canRun()) { 38 | record.setResponseResult(new JSONObject()); 39 | record.setCode(TEST_ERROR_CODE); 40 | record.setResult(RunResult.UNRUN.getCode()); 41 | record.setCheckResult(bean.getTestWish()); 42 | return; 43 | } 44 | int envId = bean.getEnvId(); 45 | int serviceId = bean.getServiceId(); 46 | String host = service.getHost(envId, serviceId); 47 | FunRequest request = null; 48 | String httpType = bean.getHttpType(); 49 | if (httpType.equalsIgnoreCase(RequestType.GET.getDesc())) { 50 | request = FunRequest.isGet().setHost(host).setApiName(bean.getUrl()).addHeaders(bean.getHeaders()).addArgs(bean.getParams()); 51 | } else if (httpType.equalsIgnoreCase(RequestType.POST_JSON.getDesc())) { 52 | request = FunRequest.isPost().setHost(host).setApiName(bean.getUrl()).addHeaders(bean.getHeaders()).addJson(bean.getParams()); 53 | } else if (httpType.equalsIgnoreCase(RequestType.POST_FORM.getDesc())) { 54 | request = FunRequest.isPost().setHost(host).setApiName(bean.getUrl()).addHeaders(bean.getHeaders()).addParams(bean.getParams()); 55 | } else { 56 | logger.warn("请求方式不支持:{}", bean.toString()); 57 | record.setResult(RunResult.UNRUN.getCode()); 58 | return; 59 | } 60 | JSONObject response = request.getResponse(); 61 | record.setResponseResult(response); 62 | if (response.isEmpty()) { 63 | logger.warn("用例响应为空:{}", bean.toString()); 64 | record.fail(RunResult.UNRUN, bean); 65 | return; 66 | } 67 | record.setCode(VerifyResponseUtil.getCode(response)); 68 | boolean verify = VerifyResponseUtil.verify(response, bean.getTestWish()); 69 | record.setResult(verify ? RunResult.SUCCESS.getCode() : RunResult.FAIL.getCode()); 70 | record.setCheckResult(bean.getTestWish()); 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/wapper/RequestWrapper.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.wapper; 2 | 3 | import com.okay.family.fun.config.Constant; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.servlet.ReadListener; 8 | import javax.servlet.ServletInputStream; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletRequestWrapper; 11 | import java.io.*; 12 | 13 | public class RequestWrapper extends HttpServletRequestWrapper { 14 | 15 | private static Logger logger = LoggerFactory.getLogger(RequestWrapper.class); 16 | 17 | private final String body; 18 | 19 | public RequestWrapper(HttpServletRequest request) { 20 | super(request); 21 | StringBuilder stringBuilder = new StringBuilder(); 22 | BufferedReader bufferedReader = null; 23 | InputStream inputStream = null; 24 | try { 25 | inputStream = request.getInputStream(); 26 | if (inputStream != null) { 27 | bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 28 | char[] charBuffer = new char[128]; 29 | int bytesRead = -1; 30 | while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { 31 | stringBuilder.append(charBuffer, 0, bytesRead); 32 | } 33 | } else { 34 | stringBuilder.append(Constant.EMPTY); 35 | } 36 | } catch (IOException ex) { 37 | logger.error("获取请求body发生错误", ex); 38 | } finally { 39 | if (inputStream != null) { 40 | try { 41 | inputStream.close(); 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | if (bufferedReader != null) { 47 | try { 48 | bufferedReader.close(); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | } 54 | body = stringBuilder.toString(); 55 | } 56 | 57 | @Override 58 | public ServletInputStream getInputStream() throws IOException { 59 | final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); 60 | ServletInputStream servletInputStream = new ServletInputStream() { 61 | @Override 62 | public boolean isFinished() { 63 | return false; 64 | } 65 | 66 | @Override 67 | public boolean isReady() { 68 | return false; 69 | } 70 | 71 | @Override 72 | public void setReadListener(ReadListener readListener) { 73 | } 74 | 75 | @Override 76 | public int read() throws IOException { 77 | return byteArrayInputStream.read(); 78 | } 79 | }; 80 | return servletInputStream; 81 | 82 | } 83 | 84 | @Override 85 | public BufferedReader getReader() throws IOException { 86 | return new BufferedReader(new InputStreamReader(this.getInputStream())); 87 | } 88 | 89 | public String getBody() { 90 | return this.body; 91 | } 92 | 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/utils/RString.groovy: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.utils 2 | 3 | import com.okay.family.fun.frame.SourceCode 4 | 5 | 6 | class RString extends SourceCode { 7 | 8 | static char[] chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', (char) 65, (char) 66, (char) 67, (char) 68, (char) 69, (char) 70, (char) 71, (char) 72, (char) 73, (char) 74, (char) 75, (char) 76, (char) 77, (char) 78, (char) 79, (char) 80, (char) 81, (char) 82, (char) 83, (char) 84, (char) 85, (char) 86, (char) 87, (char) 88, (char) 89, (char) 90, (char) 97, (char) 98, (char) 99, (char) 100, (char) 101, (char) 102, (char) 103, (char) 104, (char) 105, (char) 106, (char) 107, (char) 108, (char) 109, (char) 110, (char) 111, (char) 112, (char) 113, (char) 114, (char) 115, (char) 116, (char) 117, (char) 118, (char) 119, (char) 120, (char) 121, (char) 122] 9 | 10 | static String[] chineses = ["〇", "一", "二", "三", "四", "五", "六", "七", "八", "九"] 11 | 12 | static String[] capeChineses = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"] 13 | 14 | /** 15 | * 获取随机字符串 16 | * @param i 17 | * @return 18 | */ 19 | static String getString(int i) { 20 | def re = new StringBuffer() 21 | if (i < 1) return re 22 | for (int j in 1..i) { 23 | re.append(getChar()) 24 | } 25 | re.toString() 26 | } 27 | 28 | /** 29 | * 获取随机字符 30 | * @return 31 | */ 32 | static char getChar() { 33 | chars[getRandomInt(62) - 1] 34 | } 35 | 36 | /** 37 | * 获取随机字母,区分大小写 38 | * 39 | * @return 40 | */ 41 | static char getWord() { 42 | chars[getRandomInt(52) + 9]; 43 | } 44 | 45 | /** 46 | * 获取随机字符串,没有数字 47 | * @param i 48 | * @return 49 | */ 50 | static String getStringWithoutNum(int i) { 51 | def re = new StringBuffer() 52 | if (i < 1) return re 53 | for (int j in 1..i) { 54 | re.append(getWord()) 55 | } 56 | re.toString() 57 | } 58 | 59 | /** 60 | * 获取所有小写字母 61 | * @return 62 | */ 63 | static String getAllLowWord() { 64 | "abcdefghijklmnopqrstuvwxyz" 65 | } 66 | 67 | /** 68 | * 获取所有大写字母 69 | * @return 70 | */ 71 | static String getAllUpWord() { 72 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 73 | } 74 | 75 | /** 76 | * 获取所有的数字 77 | * @return 78 | */ 79 | static String getAllNumber() { 80 | "0123456789" 81 | } 82 | 83 | /** 84 | * 将int类型转化为汉子数字,对于3位数的数字自动补零 85 | * @param i 86 | * @return 87 | */ 88 | static String getChinese(int i) { 89 | if (i <= 0) return "〇〇〇" 90 | String num = (i + EMPTY).collect {x -> chineses[changeStringToInt(x)]}.join() 91 | num.length() > 2 ? num : getManyString(chineses[0] + EMPTY, 3 - num.length()) + num 92 | } 93 | 94 | /** 95 | * 将int类型转化汉字大写数字表示,对于3位数的数字自动补零 96 | * @param i 97 | * @return 98 | */ 99 | static String getCapeChinese(int i) { 100 | if (i <= 0) return "零零零" 101 | def num = (i + EMPTY).collect {x -> capeChineses[changeStringToInt(x)]}.join() 102 | num.length() > 2 ? num : getManyString(capeChineses[0] + EMPTY, 3 - num.length()) + num 103 | 104 | } 105 | } -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/Save.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.okay.family.fun.utils.WriteRead; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.io.File; 10 | import java.util.ArrayList; 11 | import java.util.Collection; 12 | import java.util.List; 13 | 14 | /** 15 | * 用来保存数据的类,如果文件已经存在会删除原来的文件 16 | */ 17 | public class Save extends SourceCode { 18 | 19 | private static Logger logger = LoggerFactory.getLogger(Save.class); 20 | 21 | /** 22 | * 保存信息,每次回删除文件,默认当前工作空间 23 | * 24 | * @param content 内容 25 | */ 26 | public static void info(String content) { 27 | info("long", content); 28 | } 29 | 30 | public static void info(String name, String content) { 31 | File dirFile = new File(LONG_Path + name); 32 | if (dirFile.exists()) dirFile.delete(); 33 | WriteRead.writeText(dirFile, content); 34 | logger.info("数据保存成功!文件名:{}{}", LONG_Path, name); 35 | } 36 | 37 | /** 38 | * 保存list数据到本地文件 39 | */ 40 | public static void saveLongList(Collection data, Object name) { 41 | List list = new ArrayList<>(); 42 | data.forEach(num -> list.add(num.toString())); 43 | saveStringList(list, name.toString()); 44 | data.removeAll(data); 45 | } 46 | 47 | /** 48 | * 保存list数据到本地文件 49 | */ 50 | public static void saveIntegerList(Collection data, String name) { 51 | List list = new ArrayList<>(); 52 | data.forEach(num -> list.add(num.toString())); 53 | saveStringList(list, name); 54 | } 55 | 56 | /** 57 | * 保存list数据到本地文件 58 | */ 59 | public static void saveDoubleList(Collection data, String name) { 60 | List list = new ArrayList<>(); 61 | data.forEach(num -> list.add(num.toString())); 62 | saveStringList(list, name); 63 | } 64 | 65 | /** 66 | * 保存list数据,long类型无法覆盖 67 | * 68 | * @param data 69 | * @param name 70 | */ 71 | public static void saveList(Collection data, String name) { 72 | List list = new ArrayList<>(); 73 | data.forEach(num -> list.add(num.toString())); 74 | saveStringList(list, name); 75 | } 76 | 77 | /** 78 | * 保存list数据到本地文件 79 | */ 80 | public static void saveStringList(Collection data, String name) { 81 | String join = StringUtils.join(data, LINE); 82 | info(name, join); 83 | } 84 | 85 | /** 86 | * 保存json数据到本地文件 87 | */ 88 | public static void saveJson(JSONObject data, String name) { 89 | StringBuffer buffer = new StringBuffer(); 90 | data.keySet().forEach(x -> buffer.append(LINE + x.toString() + PART + data.getString(x.toString()))); 91 | info(name, buffer.toString().substring(2)); 92 | } 93 | 94 | /** 95 | * 同步save数据,用于匿名类多线程保存测试数据 96 | * 97 | * @param data 98 | * @param name 99 | */ 100 | public static void saveStringListSync(Collection data, String name) { 101 | synchronized (Save.class) { 102 | if (data.isEmpty()) return; 103 | saveStringList(data, name); 104 | } 105 | } 106 | 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/common/basedata/OkayConstant.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.common.basedata; 2 | 3 | import com.okay.family.fun.config.Constant; 4 | import com.okay.family.fun.frame.SourceCode; 5 | 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * 常量配置类 10 | */ 11 | public class OkayConstant extends SourceCode { 12 | 13 | /** 14 | * 日志追踪header字段,不区分大小写 15 | */ 16 | public static final String REQUEST_ID = "requestid"; 17 | 18 | /** 19 | * 默认的requestid前缀 20 | */ 21 | public static final String REQUEST_ID_PREFIX = "family"; 22 | 23 | /** 24 | * 用户标记请求对象的header字段 25 | */ 26 | public static final String MARK_HEADER = "mark"; 27 | 28 | /** 29 | * 获取用户凭证标记 30 | */ 31 | public static final String USER_CERTIFICATE_KEY = "uid="; 32 | 33 | public static final String RANDOM_KEY = "random="; 34 | 35 | public static final String RUN_RESULT_TEXT = "<校验结果>"; 36 | 37 | public static final String PATTEN_ERROR_TEXT = "正则表达式错误"; 38 | 39 | public static final String MOCO_KEY = "name"; 40 | 41 | public static final String MOCO_VALUE = "demo"; 42 | 43 | public static final String MOCO_CHILDREN = "children"; 44 | 45 | public static final String DEFAULT_VERIFY_DEC = "默认验证"; 46 | 47 | public static final String RULE = "规则一:value填写'uid=123',表示使用id为123的用户账号其登录token值" + LINE_HTML + "规则二:可在header以及上行参数的value中填写随机数,使用语法如下。" + LINE_HTML + "例:random=1000,2000" + LINE_HTML + "注:后者值需大于前者,否则生成随机数功能不可用"; 48 | 49 | public static final String SIMPLER_RESULT_KEY_ID = "id"; 50 | 51 | public static final String SIMPLER_RESULT_KEY_NAME = "name"; 52 | 53 | /** 54 | * 用于处理list对象的写入和读取分隔 55 | */ 56 | public static final String MYSQL_SEPARATE = Constant.PERCENT[1]; 57 | 58 | /** 59 | * 用户身份数量 60 | */ 61 | public static final long ROLE = 6L; 62 | 63 | /** 64 | * 用户状态数量 65 | */ 66 | public static final long USER_STATUS = 4L; 67 | 68 | /** 69 | * 环境数量 70 | */ 71 | public static final long ENV = 5L; 72 | 73 | /** 74 | * 用户凭证过期时间 75 | */ 76 | public static final long CERTIFICATE_TIMEOUT = 10 * 60 * 1000L; 77 | 78 | /** 79 | * 域名信息缓存时间,s 80 | */ 81 | public static final int HOST_TIMEOUT = 1_000; 82 | 83 | /** 84 | * 分布式锁过期时间,ms 85 | */ 86 | public static final int LOCK_TIMEOUT = 60_000; 87 | 88 | /** 89 | * 分布式锁等待间隔毫秒 90 | */ 91 | public static final int WAIT_INTERVAL = 200; 92 | 93 | /** 94 | * 分布式锁最大等待次数 95 | */ 96 | public static final int WAIT_MAX_TIME = 15; 97 | 98 | /** 99 | * 节点锁 100 | */ 101 | public static final long NODE_LOCK = 1L; 102 | 103 | /** 104 | * 异步线程等待时间 105 | */ 106 | public static final long SYNC_WAIT_TIMEOUT = 10L; 107 | 108 | /** 109 | * 生成全局唯一变量,用于用例运行id 110 | */ 111 | public static AtomicInteger RUN_MARK; 112 | 113 | /** 114 | * 生成全局唯一变量,用于用例集用例id 115 | */ 116 | public static AtomicInteger COLLECTION_MARK; 117 | 118 | /** 119 | * 节点 120 | */ 121 | public static int node; 122 | 123 | public static final int HOTFIX = 1; 124 | 125 | public static final int DEV = 2; 126 | 127 | public static final int STRESS = 3; 128 | 129 | public static final int ONLINE = 4; 130 | 131 | 132 | } 133 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | @rem Execute Gradle 88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 89 | 90 | :end 91 | @rem End local scope for the variables with windows NT shell 92 | if "%ERRORLEVEL%"=="0" goto mainEnd 93 | 94 | :fail 95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 96 | rem the _cmd.exe /c_ return code! 97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 98 | exit /b 1 99 | 100 | :mainEnd 101 | if "%OS%"=="Windows_NT" endlocal 102 | 103 | :omega 104 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/base/constaint/ThreadLimitTimeCount.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.base.constaint; 2 | 3 | 4 | import com.okay.family.fun.base.interfaces.MarkThread; 5 | import com.okay.family.fun.config.HttpClientConstant; 6 | import com.okay.family.fun.frame.execute.Concurrent; 7 | import com.okay.family.fun.frame.httpclient.GCThread; 8 | import com.okay.family.fun.utils.Time; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * 请求时间限制的多线程类,限制每个线程执行的时间 17 | *

18 | * 通常在测试某项用例固定时间的场景下使用,可以提前终止测试用例 19 | *

20 | * 21 | * @param 闭包参数传递使用,Groovy脚本会有一些兼容问题,部分对象需要tostring获取参数值 22 | */ 23 | public abstract class ThreadLimitTimeCount extends ThreadBase { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTimeCount.class); 26 | 27 | public List marks = new ArrayList<>(); 28 | 29 | /** 30 | * 全局的时间终止开关 31 | */ 32 | private static boolean key = false; 33 | 34 | /** 35 | * 任务请求执行时间,单位是秒 36 | */ 37 | public int time; 38 | 39 | public ThreadLimitTimeCount(T t, int time, MarkThread markThread) { 40 | this.time = time * 1000; 41 | this.t = t; 42 | this.mark = markThread; 43 | } 44 | 45 | protected ThreadLimitTimeCount() { 46 | super(); 47 | } 48 | 49 | @Override 50 | public void run() { 51 | try { 52 | before(); 53 | List t = new ArrayList<>(); 54 | long ss = Time.getTimeStamp(); 55 | long et = ss; 56 | while (true) { 57 | try { 58 | threadmark = mark == null ? EMPTY : this.mark.mark(this); 59 | long s = Time.getTimeStamp(); 60 | doing(); 61 | et = Time.getTimeStamp(); 62 | executeNum++; 63 | long diff = et - s; 64 | t.add(diff); 65 | if (diff > HttpClientConstant.MAX_ACCEPT_TIME) marks.add(diff + CONNECTOR + threadmark); 66 | if ((et - ss) > time || status() || key) break; 67 | } catch (Exception e) { 68 | logger.warn("执行任务失败!", e); 69 | logger.warn("执行失败对象的标记:{}", threadmark); 70 | errorNum++; 71 | } 72 | } 73 | long ee = Time.getTimeStamp(); 74 | logger.info("执行次数:{}, 失败次数: {},总耗时: {} s", executeNum, errorNum, (ee - ss) / 1000 + 1); 75 | Concurrent.allTimes.addAll(t); 76 | Concurrent.requestMark.addAll(marks); 77 | } catch (Exception e) { 78 | logger.warn("执行任务失败!", e); 79 | } finally { 80 | after(); 81 | } 82 | 83 | } 84 | 85 | /** 86 | * 用于在某些情况下提前终止测试 87 | */ 88 | public static void stopAllThread() { 89 | key = true; 90 | } 91 | 92 | public boolean status() { 93 | return errorNum > 10; 94 | } 95 | 96 | /** 97 | * 运行待测方法的之前的准备 98 | */ 99 | @Override 100 | public void before() { 101 | key = false; 102 | } 103 | 104 | @Override 105 | protected void after() { 106 | super.after(); 107 | marks = new ArrayList<>(); 108 | GCThread.stop(); 109 | } 110 | 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/groovy/com/okay/family/fun/frame/socket/SocketClient.java: -------------------------------------------------------------------------------- 1 | package com.okay.family.fun.frame.socket; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.okay.family.fun.base.bean.AbstractBean; 5 | import com.okay.family.fun.base.exception.ParamException; 6 | import org.java_websocket.client.WebSocketClient; 7 | import org.java_websocket.handshake.ServerHandshake; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.io.IOException; 12 | import java.io.Serializable; 13 | import java.net.URI; 14 | import java.net.URISyntaxException; 15 | import java.nio.charset.Charset; 16 | 17 | /** 18 | * socket客户端代码 19 | */ 20 | public class SocketClient extends WebSocketClient implements Serializable { 21 | 22 | private static final long serialVersionUID = 1306796619468953402L; 23 | 24 | private static Logger logger = LoggerFactory.getLogger(SocketClient.class); 25 | 26 | private SocketClient(URI uri) { 27 | super(uri); 28 | } 29 | 30 | public static SocketClient getInstance(String url) { 31 | URI uri = null; 32 | try { 33 | uri = new URI(url); 34 | } catch (URISyntaxException e) { 35 | ParamException.fail("创建socket client 失败! 原因:" + e.getMessage()); 36 | } 37 | return new SocketClient(uri); 38 | } 39 | 40 | @Override 41 | public void onOpen(ServerHandshake handshakedata) { 42 | logger.info("开始建立socket连接..."); 43 | handshakedata.iterateHttpFields().forEachRemaining(x -> logger.info("握手信息key: {} ,value: {}", x, handshakedata.getFieldValue(x))); 44 | } 45 | 46 | /** 47 | * 收到消息时候调用的方法 48 | * 49 | * @param message 50 | */ 51 | @Override 52 | public void onMessage(String message) { 53 | logger.info("收到: {}", message); 54 | } 55 | 56 | /** 57 | * 关闭,存疑.线程结束会自动关闭.不可调用websocketclient中的clone()方法 58 | * 59 | * @param code 60 | * @param reason 61 | * @param remote 62 | */ 63 | @Override 64 | public void onClose(int code, String reason, boolean remote) { 65 | logger.info("socket 连接关闭..."); 66 | try { 67 | getSocket().close(); 68 | } catch (IOException e) { 69 | logger.error("socket连接关闭失败!", e); 70 | } 71 | } 72 | 73 | @Override 74 | public void onError(Exception e) { 75 | logger.error("socket异常!", e); 76 | } 77 | 78 | @Override 79 | public void send(String text) { 80 | logger.debug("发送:{}", text); 81 | super.send(text); 82 | } 83 | 84 | /** 85 | * 发送非默认编码格式的文字 86 | * 87 | * @param text 88 | * @param charset 89 | */ 90 | public void send(String text, Charset charset) { 91 | send(new String(text.getBytes(), charset)); 92 | } 93 | 94 | /** 95 | * 发送json信息 96 | * 97 | * @param json 98 | */ 99 | public void send(JSONObject json) { 100 | send(json.toJSONString()); 101 | } 102 | 103 | /** 104 | * 发送bean 105 | * 106 | * @param bean 107 | */ 108 | public void send(AbstractBean bean) { 109 | send(bean.toString()); 110 | } 111 | 112 | /** 113 | * 该方法用于性能测试中,clone多线程对象 114 | * 115 | * @return 116 | */ 117 | @Override 118 | public SocketClient clone() { 119 | return new SocketClient(this.uri); 120 | } 121 | 122 | 123 | } 124 | --------------------------------------------------------------------------------