content: package com.alibaba.markovdemo.engine;
  
  
  import com.alibaba.fastjson.JSON;
  import com.alibaba.fastjson.JSONObject;
  import com.alibaba.markovdemo.BO.TestCaseInput;
  import com.alibaba.markovdemo.BO.TestRespone;
  import com.alibaba.markovdemo.common.Layout;
  import com.alibaba.markovdemo.engine.plugins.Pipeline;
  
  import com.alibaba.markovdemo.engine.stages.*;
  import com.alibaba.markovdemo.engine.util.Toolkit;
  import com.alibaba.markovdemo.entity.GotDatasource;
  import com.alibaba.markovdemo.entity.GotPipeline;
  import com.alibaba.markovdemo.entity.PipelineImpl;
  import com.alibaba.markovdemo.service.DatasourceService;
  import com.alibaba.markovdemo.service.PipelineService;
  import com.google.gson.Gson;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  
  
  import java.io.IOException;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  
  @Service
  public class SingleController {
  
      private static final Logger logger = LoggerFactory.getLogger(SingleController.class);
  
      private static final String PARAMS = "params";
  
  
      @Autowired
      PipelineService pipelineService;
      @Autowired
      DatasourceService datasourceService;
  
      /**
       * 函数功能:根据pipeline获取动态布局
       * @param scenarioId
       */
      public Layout getLayout(final Long scenarioId) throws IOException {
  
          // 获取pipeline
          GotPipeline gotPipeline = pipelineService.getPipeline(scenarioId);
          JSONObject pipelineJsonObj = JSON.parseObject(gotPipeline.getPipeline());
  
          //获取datasource
          Layout layout = new Layout();
          layout.setCaseName("case名");
          layout.setCaseDese("case描述,展现在列表页的简单描述");
          layout.setCaseLongDese("case描述,展现在列表页的简单描述");
  
          Pipeline pipelineObj = new Pipeline();
          pipelineObj.build(pipelineJsonObj);
          //数据准备阶段
          PrepareDataStage prepareDataStage = (PrepareDataStage)pipelineObj.flow.get(StageName.prepareData);
          if (prepareDataStage != null){
              //生成pipeline阶段中的数据准备流程
              layout.getPipelineStage().put(StageName.prepareData, prepareDataStage.buildLayout());
  
          }
          //执行阶段
          CompositeBaseStage runStage = (CompositeBaseStage)pipelineObj.flow.get(StageName.caseRunStage);
          if (runStage!= null){
              //生成pipeline阶段中的run流程
              layout.getPipelineStage().put(StageName.caseRunStage,runStage.buildPipelineLayout());
              layout.setCaseRunStage(runStage.buildCaseRunLayout());
          }
  
          //todo:此处直接使用pipeline中的demo数据源配置,为了方便,但在实际中可以不这么做,而是走数据源动态化的方式
          try {
              layout.setDataPrepareStageNew(pipelineJsonObj.getJSONObject("layoutConf").getJSONObject("dataPrepareStageNew"));
          }catch(Exception e){
              e.printStackTrace();
          }
          return layout;
      }
  
      /**
       * 函数功能:占位符替换
       * @param testCase
       * @return
       */
      public String placeholderReplace(TestCaseInput testCase) {
          //将转化为json串后整体进行替换
          Gson gosn = new Gson();
          String testCaseJsonStr = gosn.toJson(testCase);
          return Toolkit.placeholderReplace(testCaseJsonStr);
      }
  
  
      /**
       * 函数功能:单次用例运行
       * @param testCase
       * @param pipelineJsonObj
       * @return
       */
      public TestRespone runCase(TestCaseInput testCase, JSONObject pipelineJsonObj){
  
          Map<StageName,Object> stageParams = new HashMap<>();
          TestRespone testRespone = new TestRespone();
          try{
  
              //环境初始化
              //todo:to be fill.. 用户可根据自己测试服务进行测试环境初始化工作,比如基于容器镜像/rpm的部署方式
              logger.info("加载环境为:"+testCase.getEnvName());
              //初始化pipeline
              PipelineImpl pipelineObj = new PipelineImpl();
              pipelineObj.build(pipelineJsonObj);
  
              testRespone.setCaseTemplate("C++");
              //加入部署数据
              stageParams.put(StageName.deploy,testCase.getEnvName());
              //用例占位符替换
              String testCaseStr = placeholderReplace(testCase);
              //初始化testcase
              TestCaseData testCaseDataObj= TestCaseData.build(JSONObject.parseObject(testCaseStr));
              Map<String,List<RunData>> stageRunDataMap = new HashMap<>();
              //执行每阶段:1.数据准备,2.用例执行
              for(StageName stageName :pipelineObj.flow.keySet()){
  
                  logger.info("[运行开始],当前阶段:" + stageName.name());
                  BaseStage bs = pipelineObj.flow.get(stageName);
                  bs.setStageRunDataMap(stageRunDataMap);
                  //设置testcase输入
                  if (testCaseDataObj.testCaseInputMap.containsKey(stageName)){
                      bs.setIputData(testCaseDataObj.testCaseInputMap.get(stageName));
                      //初始化RunData,作为执行参数,将在各个插件间进行传递
                      bs.setRunData();
                  }
                  //设置stage之间传递的参数
                  bs.setStageParams(stageParams);
                  int retryNum = getRetryNum(bs.getStageJsonObj());
                  int i = 0;
                  //判断是否需要重试,如果最终结果是
                  do{
                      i++;
                      if(i > 1){
                          int n = i-1;
                          logger.info("[失败重试运行中],当前重试第" + n + "次");
                      }
                      //执行before_exec, exec, after_exec
                      bs.beforeExec();
                      bs.exec();
                      bs.afterExec();
                      stageRunDataMap.put(stageName.name(),bs.getRunDataList());
                      stageParams = bs.getStageParams();
                      //填充返回结果
                      testRespone = bs.setTestRespone(testRespone);
                  } while(i <= retryNum && !testRespone.getStatus().equals(ResultStatus.SUCCESS));
  
              }
  
          }
          //如有抛异常
          catch (Exception e) {
              logger.error("运行过程出现异常,请检查!");
              testRespone.setStatus(ResultStatus.ERROR);
  
          }
          return testRespone;
  
      }
  
      /**
       * 函数功能:获取重试次数
       * 可在pipeline中进行配置
       * @param pipelineBsJson
       * @return
       */
      public int getRetryNum(JSONObject pipelineBsJson){
          int retryNum = 0;
          if (pipelineBsJson != null && pipelineBsJson.containsKey(PARAMS)){
              JSONObject paramsObj = (JSONObject)pipelineBsJson.get(PARAMS);
              retryNum = paramsObj.containsKey("retryNum") ? (int)paramsObj.get("retryNum") : 0;
          }
          return retryNum;
      }
  
  
  
  
  
  }
  