package zentaoHelper
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"github.com/bitly/go-simplejson"
commConsts "github.com/easysoft/zentaoatf/internal/pkg/consts"
commDomain "github.com/easysoft/zentaoatf/internal/pkg/domain"
analysisHelper "github.com/easysoft/zentaoatf/internal/pkg/helper/analysis"
serverDomain "github.com/easysoft/zentaoatf/internal/server/modules/v1/domain"
httpUtils "github.com/easysoft/zentaoatf/pkg/lib/http"
i118Utils "github.com/easysoft/zentaoatf/pkg/lib/i118"
logUtils "github.com/easysoft/zentaoatf/pkg/lib/log"
stdinUtils "github.com/easysoft/zentaoatf/pkg/lib/stdin"
"github.com/fatih/color"
"github.com/jinzhu/copier"
uuid "github.com/satori/go.uuid"
)
func CommitBug(ztfBug commDomain.ZtfBug, config commDomain.WorkspaceConf) (err error) {
if ztfBug.Product == 0 {
logUtils.Info(color.RedString(i118Utils.Sprintf("ignore_bug_without_product")))
return
}
Login(config)
if ztfBug.TestType == commConsts.TestUnit {
return CommitUnitBug(&ztfBug, config)
}
ztfBug.Steps = strings.Replace(ztfBug.Steps, " ", " ", -1)
ztfBug.Steps = strings.Replace(ztfBug.Steps, "\n", "
", -1)
uri := fmt.Sprintf("/products/%d/bugs", ztfBug.Product)
url := GenApiUrl(uri, nil, config.Url)
bug := commDomain.ZentaoBug{}
copier.Copy(&bug, ztfBug)
_, err = httpUtils.Post(url, bug)
if err != nil {
err = ZentaoRequestErr(url, i118Utils.Sprintf("fail_to_report_bug", err.Error()))
return
}
logUtils.Info(color.GreenString(i118Utils.Sprintf("success_to_report_bug", ztfBug.Case)))
return
}
func CommitUnitBug(ztfBug *commDomain.ZtfBug, config commDomain.WorkspaceConf) (err error) {
if ztfBug.Product == 0 {
logUtils.Info(color.RedString(i118Utils.Sprintf("ignore_bug_without_product")))
return
}
if ztfBug.Title == "" {
ztfBug.Title = stdinUtils.GetInput("\\w+", "",
i118Utils.Sprintf("pls_enter")+" "+i118Utils.Sprintf("bug_title"))
}
Login(config)
submitBugs := make([]*commDomain.ZentaoBug, 0)
ztfBug.Steps = strings.Replace(ztfBug.Steps, " ", " ", -1)
ztfBug.Steps = strings.Replace(ztfBug.Steps, "\n", "
", -1)
ztfBug.Title = strings.Trim(ztfBug.Title, "-")
bug := commDomain.ZentaoBug{}
copier.Copy(&bug, ztfBug)
submitBugs = append(submitBugs, &bug)
generateCaseId(submitBugs, config)
for _, bug := range submitBugs {
uri := fmt.Sprintf("/products/%d/bugs", bug.Product)
url := GenApiUrl(uri, nil, config.Url)
_, err = httpUtils.Post(url, bug)
if err != nil {
err = ZentaoRequestErr(url, i118Utils.Sprintf("fail_to_report_bug", err.Error()))
return
}
logUtils.Info(color.GreenString(i118Utils.Sprintf("success_to_report_bug", bug.Case)))
}
return
}
func PrepareBug(workspacePath, seq string, caseIdStr string, productId int) (bug commDomain.ZtfBug) {
caseId, err := strconv.Atoi(caseIdStr)
if err != nil {
return
}
report, _, err := analysisHelper.ReadReportByWorkspaceSeq(workspacePath, seq)
if err != nil {
return
}
for _, cs := range report.FuncResult {
if cs.Id != caseId || cs.Status != commConsts.FAIL {
continue
}
steps := make([]string, 0)
stepsArray := make([]map[string]interface{}, 0)
stepIds := ""
for _, step := range cs.Steps {
if step.Status == commConsts.FAIL {
stepIds += step.Id + "_"
}
stepIds = strings.Trim(stepIds, "_")
stepsContent := GenBugStepText(step)
steps = append(steps, stepsContent)
stepsArray = append(stepsArray, map[string]interface{}{
"title": step.Name,
"status": step.Status,
"steps": stepsContent,
})
}
bug = commDomain.ZtfBug{
Title: cs.Title,
TestType: "func",
Case: cs.Id,
Product: productId,
Steps: strings.Join(steps, "\n"),
StepIds: stepIds,
Uid: uuid.NewV4().String(),
Type: "codeerror", Severity: 3, Pri: 3, OpenedBuild: []string{"trunk"},
CaseVersion: "0", OldTaskID: "0",
}
if commConsts.ExecFrom != commConsts.FromCmd {
jsonSteps, _ := json.Marshal(stepsArray)
bug.Steps = string(jsonSteps)
}
return
}
if report.TestType == commConsts.TestFunc {
return
}
bugs := make([]map[string]interface{}, 0)
stepIds := ""
hasCaseId := true
if len(report.UnitResult) == report.UnitResult[len(report.UnitResult)-1].Id {
hasCaseId = false
}
for _, cs := range report.UnitResult {
if (caseId > 0 && cs.Id != caseId) || cs.Status == "pass" {
continue
}
stepIds += strconv.Itoa(cs.Id) + "_"
steps := ""
if cs.Failure != nil {
steps = cs.Failure.Desc
}
caseId = cs.Id
if !hasCaseId {
caseId = 0
}
bugMap := map[string]interface{}{
"title": cs.Title,
"status": cs.Status,
"steps": steps,
"caseId": caseId,
"id": cs.Id,
}
bugs = append(bugs, bugMap)
break
}
bugsJSon, _ := json.Marshal(bugs)
bug = commDomain.ZtfBug{
Title: report.Name,
TestType: "unit",
Case: caseId,
Product: productId,
Steps: string(bugsJSon),
StepIds: stepIds,
Uid: uuid.NewV4().String(),
Type: "codeerror", Severity: 3, Pri: 3, OpenedBuild: []string{"trunk"},
CaseVersion: "0", OldTaskID: "0",
}
return
}
func GenBugStepText(step commDomain.StepLog) string {
stepResults := make([]string, 0)
stepId, _ := strconv.Atoi(step.Id)
stepId += 1
stepTxt := fmt.Sprintf("步骤%d: %s %s\n", stepId, step.Name, step.Status)
for _, checkpoint := range step.CheckPoints {
text := fmt.Sprintf(
" 检查点:%s\n"+
" 期待结果:\n"+
" %s\n"+
" 实际结果:\n"+
" %s",
checkpoint.Status, checkpoint.Expect, checkpoint.Actual)
stepResults = append(stepResults, text)
}
return stepTxt + strings.Join(stepResults, "\n") + "\n"
}
func GetBugFiledOptions(config commDomain.WorkspaceConf, productId int) (
bugFields commDomain.ZentaoBugFields, err error) {
err = Login(config)
if err != nil {
return
}
uri := fmt.Sprintf("/options/bug?product=%d", productId)
url := GenApiUrl(uri, nil, config.Url)
bytes, err := httpUtils.Get(url)
bugOptionsWrapper := commDomain.BugOptionsWrapper{}
if err != nil {
err = ZentaoRequestErr(url, err.Error())
return
}
err = json.Unmarshal(bytes, &bugOptionsWrapper)
if err != nil {
err = ZentaoRequestErr(url, commConsts.ResponseParseErr.Message)
return
}
bugFields.Types = fieldMapToListOrderByStr(bugOptionsWrapper.Options.Type, false)
bugFields.Pri = fieldArrToListKeyStr(bugOptionsWrapper.Options.Pri, false)
bugFields.Severity = fieldMapToListOrderByInt(bugOptionsWrapper.Options.Severity)
bugFields.Modules = fieldMapToListOrderByInt(bugOptionsWrapper.Options.Modules)
bugFields.Build = fieldMapToListOrderByStr(bugOptionsWrapper.Options.Build, true)
return
}
func LoadBugs(Product int, config commDomain.WorkspaceConf) (bugs []commDomain.ZentaoBug, err error) {
Login(config)
uri := fmt.Sprintf("/products/%d/bugs", Product)
params := map[string]interface{}{
"limit": 10000,
}
url := GenApiUrl(uri, params, config.Url)
bytes, err := httpUtils.Get(url)
if err != nil {
err = ZentaoRequestErr(url, err.Error())
return
}
jsn, err := simplejson.NewJson(bytes)
if err != nil {
err = ZentaoRequestErr(url, commConsts.ResponseParseErr.Message)
return
}
items, err := jsn.Get("bugs").Array()
for _, item := range items {
bug, _ := item.(map[string]interface{})
id, _ := bug["id"].(json.Number).Int64()
caseId, _ := bug["case"].(json.Number).Int64()
severity, _ := bug["severity"].(json.Number).Int64()
pri, _ := bug["pri"].(json.Number).Int64()
title, _ := bug["title"].(string)
openedBy, _ := bug["openedBy"].(map[string]interface{})
bugs = append(bugs, commDomain.ZentaoBug{
Id: int(id),
Title: title,
Case: int(caseId),
Steps: bug["steps"].(string),
Type: bug["type"].(string),
Severity: int(severity),
Pri: int(pri),
StatusName: bug["statusName"].(string),
OpenedDate: bug["openedDate"].(string),
OpenedBy: openedBy["realname"].(string),
})
}
return
}
func generateCaseId(bugs []*commDomain.ZentaoBug, config commDomain.WorkspaceConf) (caseId int) {
if len(bugs) == 0 {
return
}
//查询所有case,标题相同则返回
casesResp, _ := ListCaseByProduct(config.Url, bugs[0].Product)
for _, bug := range bugs {
for _, cs := range casesResp.Cases {
if cs.Title == bug.Title {
bug.Case = cs.Id
break
}
}
if bug.Case == 0 {
caseInfo, _ := CreateCase(bug.Product, bug.Title, nil, serverDomain.TestScript{}, config)
bug.Case = caseInfo.Id
}
}
return
}