<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - <NAME> <EMAIL>

package scribe

import (
	"encoding/json"
	"fmt"
	"strings"
)

// Describes the results of a test. The type can be marshaled into a JSON
// string as required.
type TestResult struct {
	TestID      string    `json:"testid" yaml:"testid"`                 // The identifier for the test.
	TestName    string    `json:"name" yaml:"name"`                     // Optional test name for display
	Description string    `json:"description" yaml:"description"`       // Test description
	Tags        []TestTag `json:"tags,omitempty" yaml:"tags,omitempty"` // Tags for the test.

	IsError bool   `json:"iserror" yaml:"iserror"` // True of error is encountered during evaluation.
	Error   string `json:"error" yaml:"error"`     // Error associated with test.

	MasterResult   bool `json:"masterresult" yaml:"masterresult"`     // Master result of test.
	HasTrueResults bool `json:"hastrueresults" yaml:"hastrueresults"` // True if > 0 evaluations resulted in true.

	Results []TestSubResult `json:"results" yaml:"results"` // The sub-results for the test.
}

// For a given test, a number of sources can be identified that match the
// criteria. For example, multiple files can be identifier with a given
// filename. Each test tracks individual results for these cases.
type TestSubResult struct {
	Result     bool   `json:"result" yaml:"result"`         // The result of evaluation for an identifier source.
	Identifier string `json:"identifier" yaml:"identifier"` // The identifier for the source.
}

// Return test results for a given test. Returns an error if for
// some reason the results can not be returned.
func GetResults(d *Document, name string) (TestResult, error) {
	t, err := d.getTest(name)
	if err != nil {
		return TestResult{}, err
	}
	ret := TestResult{}
	ret.TestID = t.TestID
	ret.TestName = t.TestName
	ret.Description = t.Description
	ret.Tags = t.Tags
	if t.err != nil {
		ret.Error = fmt.Sprintf("%v", t.err)
		ret.IsError = true
		return ret, nil
	}
	ret.MasterResult = t.masterResult
	ret.HasTrueResults = t.hasTrueResults
	for _, x := range t.results {
		nr := TestSubResult{}
		nr.Result = x.result
		nr.Identifier = x.criteria.identifier
		ret.Results = append(ret.Results, nr)
	}
	return ret, nil
}

// A helper function to convert Testresult r into a slice of greppable single
// line results. Note that each line returned is not terminated with a line
// feed.
func (r *TestResult) SingleLineResults() []string {
	lns := make([]string, 0)

	rs := "[error]"
	if !r.IsError {
		if r.MasterResult {
			rs = "[true]"
		} else {
			rs = "[false]"
		}
	}
	namestr := r.TestID
	if r.TestName != "" {
		namestr = r.TestName
	}
	buf := fmt.Sprintf("master %v name:\"%v\" id:\"%v\" hastrue:%v error:\"%v\"",
		rs, namestr, r.TestID, r.HasTrueResults, r.Error)
	lns = append(lns, buf)

	for _, x := range r.Results {
		if x.Result {
			rs = "[true]"
		} else {
			rs = "[false]"
		}
		buf := fmt.Sprintf("sub %v name:\"%v\" id:\"%v\" identifier:\"%v\"",
			rs, namestr, r.TestID, x.Identifier)
		lns = append(lns, buf)
	}

	return lns
}

// A helper function to convert TestResult into a JSON string.
func (r *TestResult) JSON() string {
	buf, err := json.Marshal(r)
	if err != nil {
		fmt.Sprintf("JSON encoding error: %v", err)
	}
	return string(buf)
}

// A helper function to convert TestResult into a human readable result
// suitable for display.
func (r *TestResult) String() string {
	lns := make([]string, 0)
	if r.TestName != "" {
		lns = append(lns, fmt.Sprintf("result for \"%v\" (%v)", r.TestName, r.TestID))
	} else {
		lns = append(lns, fmt.Sprintf("result for \"%v\"", r.TestID))
	}
	if r.Description != "" {<commit_msg>in TestResult JSON(), fix issue with ignored fmt.Sprintf result<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - <NAME> <EMAIL>

package scribe

import (
	"encoding/json"
	"fmt"
	"strings"
)

// Describes the results of a test. The type can be marshaled into a JSON
// string as required.
type TestResult struct {
	TestID      string    `json:"testid" yaml:"testid"`                 // The identifier for the test.
	TestName    string    `json:"name" yaml:"name"`                     // Optional test name for display
	Description string    `json:"description" yaml:"description"`       // Test description
	Tags        []TestTag `json:"tags,omitempty" yaml:"tags,omitempty"` // Tags for the test.

	IsError bool   `json:"iserror" yaml:"iserror"` // True of error is encountered during evaluation.
	Error   string `json:"error" yaml:"error"`     // Error associated with test.

	MasterResult   bool `json:"masterresult" yaml:"masterresult"`     // Master result of test.
	HasTrueResults bool `json:"hastrueresults" yaml:"hastrueresults"` // True if > 0 evaluations resulted in true.

	Results []TestSubResult `json:"results" yaml:"results"` // The sub-results for the test.
}

// For a given test, a number of sources can be identified that match the
// criteria. For example, multiple files can be identifier with a given
// filename. Each test tracks individual results for these cases.
type TestSubResult struct {
	Result     bool   `json:"result" yaml:"result"`         // The result of evaluation for an identifier source.
	Identifier string `json:"identifier" yaml:"identifier"` // The identifier for the source.
}

// Return test results for a given test. Returns an error if for
// some reason the results can not be returned.
func GetResults(d *Document, name string) (TestResult, error) {
	t, err := d.getTest(name)
	if err != nil {
		return TestResult{}, err
	}
	ret := TestResult{}
	ret.TestID = t.TestID
	ret.TestName = t.TestName
	ret.Description = t.Description
	ret.Tags = t.Tags
	if t.err != nil {
		ret.Error = fmt.Sprintf("%v", t.err)
		ret.IsError = true
		return ret, nil
	}
	ret.MasterResult = t.masterResult
	ret.HasTrueResults = t.hasTrueResults
	for _, x := range t.results {
		nr := TestSubResult{}
		nr.Result = x.result
		nr.Identifier = x.criteria.identifier
		ret.Results = append(ret.Results, nr)
	}
	return ret, nil
}

// A helper function to convert Testresult r into a slice of greppable single
// line results. Note that each line returned is not terminated with a line
// feed.
func (r *TestResult) SingleLineResults() []string {
	lns := make([]string, 0)

	rs := "[error]"
	if !r.IsError {
		if r.MasterResult {
			rs = "[true]"
		} else {
			rs = "[false]"
		}
	}
	namestr := r.TestID
	if r.TestName != "" {
		namestr = r.TestName
	}
	buf := fmt.Sprintf("master %v name:\"%v\" id:\"%v\" hastrue:%v error:\"%v\"",
		rs, namestr, r.TestID, r.HasTrueResults, r.Error)
	lns = append(lns, buf)

	for _, x := range r.Results {
		if x.Result {
			rs = "[true]"
		} else {
			rs = "[false]"
		}
		buf := fmt.Sprintf("sub %v name:\"%v\" id:\"%v\" identifier:\"%v\"",
			rs, namestr, r.TestID, x.Identifier)
		lns = append(lns, buf)
	}

	return lns
}

// A helper function to convert TestResult into a JSON string.
func (r *TestResult) JSON() string {
	buf, err := json.Marshal(r)
	if err != nil {
		// If we are unable to marshal the result just return an empty document
		return "{}"
	}
	return string(buf)
}

// A helper function to convert TestResult into a human readable result
// suitable for display.
func (r *TestResult) String() string {
	lns := make([]string, 0)
	if r.TestName != "" {
		lns = append(lns, fmt.Sprintf("result for \"%v\" (%v)", r.TestName, r.TestID))
	} else {
		lns = append(lns, fmt.Sprintf("result for \"%v\"", r.TestID))
	}
	if r.Description != "" {
{'fraction_non_alphanumeric': 0.13739878542510123, 'fraction_numerical': 0.001771255060728745, 'mean_word_length': 3.20926517571885, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '5843602', 'n_tokens_mistral': 2650, 'n_tokens_neox': 2517, 'n_words': 897}