<commit_before>package main

import (
	"context"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/url"
	"path/filepath"

	"github.com/ovh/cds/sdk"
	"github.com/ovh/venom"
)

func runParseJunitTestResultAction(w *currentWorker) BuiltInAction {
	return func(ctx context.Context, a *sdk.Action, buildID int64, params *[]sdk.Parameter, sendLog LoggerFunc) sdk.Result {
		var res sdk.Result
		res.Status = sdk.StatusFail.String()

		pip := sdk.ParameterValue(*params, "cds.pipeline")
		proj := sdk.ParameterValue(*params, "cds.project")
		app := sdk.ParameterValue(*params, "cds.application")
		envName := sdk.ParameterValue(*params, "cds.environment")
		bnS := sdk.ParameterValue(*params, "cds.buildNumber")

		p := sdk.ParameterValue(a.Parameters, "path")
		if p == "" {
			res.Reason = fmt.Sprintf("UnitTest parser: path not provided")
			sendLog(res.Reason)
			return res
		}

		files, errg := filepath.Glob(p)
		if errg != nil {
			res.Reason = fmt.Sprintf("UnitTest parser: Cannot find requested files, invalid pattern")
			sendLog(res.Reason)
			return res
		}

		var tests venom.Tests
		sendLog(fmt.Sprintf("%d", len(files)) + " file(s) to analyze")

		for _, f := range files {
			var ftests venom.Tests

			data, errRead := ioutil.ReadFile(f)
			if errRead != nil {
				res.Reason = fmt.Sprintf("UnitTest parser: cannot read file %s (%s)", f, errRead)
				sendLog(res.Reason)
				return res
			}

			var vf venom.Tests
			if err := xml.Unmarshal(data, &vf); err != nil {
				// Check if file contains testsuite only (and no testsuites)
				if s, ok := parseTestsuiteAlone(data); ok {
					ftests.TestSuites = append(ftests.TestSuites, s)
				}
				tests.TestSuites = append(tests.TestSuites, ftests.TestSuites...)
			} else {
				tests.TestSuites = append(tests.TestSuites, vf.TestSuites...)
			}
		}

		sendLog(fmt.Sprintf("%d", len(tests.TestSuites)) + " Total Testsuite(s)")
		reasons := computeStats(&res, &tests)
		for _, r := range reasons {
			sendLog(r)
		}

		data, err := json.Marshal(tests)
		if err != nil {
			res.Reason = fmt.Sprintf("JUnit parse: failed to send tests details: %s", err)
			res.Status = sdk.StatusFail.String()
			sendLog(res.Reason)
			return res
		}

		var uri string
		if w.currentJob.wJob != nil {
			uri = fmt.Sprintf("/queue/workflows/%d/test", w.currentJob.wJob.ID)
		} else {
			uri = fmt.Sprintf("/project/%s/application/%s/pipeline/%s/build/%s/test?envName=%s", proj, app, pip, bnS, url.QueryEscape(envName))
		}

		_, code, err := sdk.Request("POST", uri, data)
		if err == nil && code > 300 {
			err = fmt.Errorf("HTTP %d", code)
		}

		if err != nil {
			res.Reason = fmt.Sprintf("JUnit parse: failed to send tests details: %s", err)
			res.Status = sdk.StatusFail.String()
			sendLog(res.Reason)
			return res
		}

		return res
	}
}

// computeStats computes failures / errors on testSuites,
// set result.Status and return a list of log to send to API
func computeStats(res *sdk.Result, v *venom.Tests) []string {
	// update global stats
	for _, ts := range v.TestSuites {
		nSkipped := 0
		for _, tc := range ts.TestCases {<commit_msg>fix (worker): junit, replace before send result (#2886)<commit_after>package main

import (
	"context"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/url"
	"path/filepath"
	"strings"

	"github.com/ovh/cds/sdk"
	"github.com/ovh/venom"
)

func runParseJunitTestResultAction(w *currentWorker) BuiltInAction {
	return func(ctx context.Context, a *sdk.Action, buildID int64, params *[]sdk.Parameter, sendLog LoggerFunc) sdk.Result {
		var res sdk.Result
		res.Status = sdk.StatusFail.String()

		pip := sdk.ParameterValue(*params, "cds.pipeline")
		proj := sdk.ParameterValue(*params, "cds.project")
		app := sdk.ParameterValue(*params, "cds.application")
		envName := sdk.ParameterValue(*params, "cds.environment")
		bnS := sdk.ParameterValue(*params, "cds.buildNumber")

		p := sdk.ParameterValue(a.Parameters, "path")
		if p == "" {
			res.Reason = fmt.Sprintf("UnitTest parser: path not provided")
			sendLog(res.Reason)
			return res
		}

		files, errg := filepath.Glob(p)
		if errg != nil {
			res.Reason = fmt.Sprintf("UnitTest parser: Cannot find requested files, invalid pattern")
			sendLog(res.Reason)
			return res
		}

		var tests venom.Tests
		sendLog(fmt.Sprintf("%d", len(files)) + " file(s) to analyze")

		for _, f := range files {
			var ftests venom.Tests

			data, errRead := ioutil.ReadFile(f)
			if errRead != nil {
				res.Reason = fmt.Sprintf("UnitTest parser: cannot read file %s (%s)", f, errRead)
				sendLog(res.Reason)
				return res
			}

			var vf venom.Tests
			if err := xml.Unmarshal(data, &vf); err != nil {
				// Check if file contains testsuite only (and no testsuites)
				if s, ok := parseTestsuiteAlone(data); ok {
					ftests.TestSuites = append(ftests.TestSuites, s)
				}
				tests.TestSuites = append(tests.TestSuites, ftests.TestSuites...)
			} else {
				tests.TestSuites = append(tests.TestSuites, vf.TestSuites...)
			}
		}

		sendLog(fmt.Sprintf("%d", len(tests.TestSuites)) + " Total Testsuite(s)")
		reasons := computeStats(&res, &tests)
		for _, r := range reasons {
			sendLog(r)
		}

		data, err := json.Marshal(tests)
		if err != nil {
			res.Reason = fmt.Sprintf("JUnit parse: failed to send tests details: %s", err)
			res.Status = sdk.StatusFail.String()
			sendLog(res.Reason)
			return res
		}

		// replace secrets in the content of the xml files analyzed
		dataS := string(data)
		for i := range logsecrets {
			if len(logsecrets[i].Value) >= 6 {
				dataS = strings.Replace(dataS, logsecrets[i].Value, "**"+logsecrets[i].Name+"**", -1)
			}
		}

		var uri string
		if w.currentJob.wJob != nil {
			uri = fmt.Sprintf("/queue/workflows/%d/test", w.currentJob.wJob.ID)
		} else {
			uri = fmt.Sprintf("/project/%s/application/%s/pipeline/%s/build/%s/test?envName=%s", proj, app, pip, bnS, url.QueryEscape(envName))
		}

		_, code, err := sdk.Request("POST", uri, []byte(dataS))
		if err == nil && code > 300 {
			err = fmt.Errorf("HTTP %d", code)
		}

		if err != nil {
			res.Reason = fmt.Sprintf("JUnit parse: failed to send tests details: %s", err)
			res.Status = sdk.StatusFail.String()
			sendLog(res.Reason)
			return res
		}

		return res
	}
}

// computeStats computes failures / errors on testSuites,
// set result.Status and return a list of log to send to API
func computeStats(res *sdk.Result, v *venom.Tests) []string {
	// update global stats
	for _, ts := range v.TestSuites {
		nSkipped := 0
		for _, tc := range ts.TestCases {
{'fraction_non_alphanumeric': 0.14961597542242702, 'fraction_numerical': 0.0027649769585253456, 'mean_word_length': 3.4934437543133194, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 5}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1053276', 'n_tokens_mistral': 2590, 'n_tokens_neox': 2312, 'n_words': 572}