github.com/kubeshop/testkube@v1.17.23/contrib/executor/jmeterd/pkg/parser/parser.go (about) 1 package parser 2 3 import ( 4 "bufio" 5 "bytes" 6 "io" 7 "strings" 8 9 "github.com/pkg/errors" 10 11 "github.com/kubeshop/testkube/pkg/api/v1/testkube" 12 ) 13 14 var ErrEmptyReport = errors.New("empty JTL report") 15 16 func ParseJTLReport(report io.Reader, resultOutput []byte) (testkube.ExecutionResult, error) { 17 var buf bytes.Buffer 18 tee := io.TeeReader(report, &buf) 19 xml := isXML(tee) 20 report = io.MultiReader(&buf, report) 21 if xml { 22 return parseXMLReport(report, resultOutput) 23 } 24 25 return parseCSVReport(report, resultOutput) 26 } 27 28 func isXML(r io.Reader) bool { 29 scanner := bufio.NewScanner(r) 30 var firstLine string 31 for scanner.Scan() { 32 line := scanner.Text() 33 trimmedLine := strings.TrimSpace(line) 34 if trimmedLine != "" { 35 firstLine = trimmedLine 36 break 37 } 38 } 39 40 return strings.HasPrefix(strings.TrimSpace(firstLine), "<?xml") || strings.HasPrefix(strings.TrimSpace(firstLine), "<testResults") 41 } 42 43 func parseXMLReport(report io.Reader, resultOutput []byte) (testkube.ExecutionResult, error) { 44 data, err := io.ReadAll(report) 45 if err != nil { 46 return testkube.ExecutionResult{}, errors.Wrap(err, "error reading jtl report") 47 } 48 49 xmlResults, err := parseXML(data) 50 if err != nil { 51 return testkube.ExecutionResult{}, errors.Wrap(err, "error parsing xml jtl report") 52 } 53 54 if xmlResults.Samples == nil && xmlResults.HTTPSamples == nil { 55 return testkube.ExecutionResult{}, errors.WithStack(ErrEmptyReport) 56 } 57 58 return mapXMLResultsToExecutionResults(resultOutput, xmlResults), nil 59 } 60 61 func parseCSVReport(report io.Reader, resultOutput []byte) (testkube.ExecutionResult, error) { 62 csvResults, err := parseCSV(report) 63 if err != nil { 64 return testkube.ExecutionResult{}, errors.Wrap(err, "error parsing csv jtl report") 65 } 66 67 if len(csvResults.Results) == 0 { 68 return testkube.ExecutionResult{}, errors.WithStack(ErrEmptyReport) 69 } 70 71 return mapCSVResultsToExecutionResults(resultOutput, csvResults), nil 72 }