<commit_before>package validation

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/golang/protobuf/ptypes"
	"google.golang.org/genproto/googleapis/devtools/cloudtrace/v2"
)

const (
	invalidTimestampMsg   = "start time must be before end time"
	malformedTimestampMsg = "unable to parse timestamp"
	missingFieldMsg       = "span is missing required fields: %v"
)

var (
	requiredMessageFields = []string{"DisplayName", "StartTime", "EndTime"}
	requiredStringFields  = []string{"Name", "SpanId"}
)

func IsSpanValid(span *cloudtrace.Span) (bool, string) {
	if isValid, msg := validateRequiredFields(span); !isValid {
		return isValid, msg
	}

	if isValid, msg := validateTimeStamps(span); !isValid {
		return isValid, msg
	}

	return true, ""
}

func validateRequiredFields(span *cloudtrace.Span) (bool, string) {
	var missingFields []string
	spanReflect := reflect.ValueOf(span)

	for _, field := range requiredStringFields {
		fieldValue := reflect.Indirect(spanReflect).FieldByName(field).String()
		if fieldValue == "" {
			missingFields = append(missingFields, field)
		}
	}

	for _, field := range requiredMessageFields {
		fieldValue := reflect.Indirect(spanReflect).FieldByName(field)
		if fieldValue.IsNil() {
			missingFields = append(missingFields, field)
		}
	}

	formattedErrMsg := fmt.Sprintf(missingFieldMsg, strings.Join(missingFields, ", "))
	return len(missingFields) == 0, formattedErrMsg
}

func validateTimeStamps(span *cloudtrace.Span) (bool, string) {
	start, err := ptypes.Timestamp(span.StartTime)
	if err != nil {
		return false, malformedTimestampMsg
	}
	end, err := ptypes.Timestamp(span.EndTime)
	if err != nil {
		return false, malformedTimestampMsg
	}

	return start.Before(end), invalidTimestampMsg
}<commit_msg>Export error messages to use in tests<commit_after>package validation

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/golang/protobuf/ptypes"
	"google.golang.org/genproto/googleapis/devtools/cloudtrace/v2"
)

const (
	InvalidTimestampMsg   = "start time must be before end time"
	MalformedTimestampMsg = "unable to parse timestamp"
	MissingFieldMsg       = "span is missing required fields: %v"
)

var (
	requiredMessageFields = []string{"DisplayName", "StartTime", "EndTime"}
	requiredStringFields  = []string{"Name", "SpanId"}
)

func IsSpanValid(span *cloudtrace.Span) (bool, string) {
	if isValid, msg := validateRequiredFields(span); !isValid {
		return isValid, msg
	}

	if isValid, msg := validateTimeStamps(span); !isValid {
		return isValid, msg
	}

	return true, ""
}

func validateRequiredFields(span *cloudtrace.Span) (bool, string) {
	var missingFields []string
	spanReflect := reflect.ValueOf(span)

	for _, field := range requiredStringFields {
		fieldValue := reflect.Indirect(spanReflect).FieldByName(field).String()
		if fieldValue == "" {
			missingFields = append(missingFields, field)
		}
	}

	for _, field := range requiredMessageFields {
		fieldValue := reflect.Indirect(spanReflect).FieldByName(field)
		if fieldValue.IsNil() {
			missingFields = append(missingFields, field)
		}
	}

	formattedErrMsg := fmt.Sprintf(MissingFieldMsg, strings.Join(missingFields, ", "))
	return len(missingFields) == 0, formattedErrMsg
}

func validateTimeStamps(span *cloudtrace.Span) (bool, string) {
	start, err := ptypes.Timestamp(span.StartTime)
	if err != nil {
		return false, MalformedTimestampMsg
	}
	end, err := ptypes.Timestamp(span.EndTime)
	if err != nil {
		return false, MalformedTimestampMsg
	}

	return start.Before(end), InvalidTimestampMsg
}
{'fraction_non_alphanumeric': 0.1222980659840728, 'fraction_numerical': 0.0011376564277588168, 'mean_word_length': 5.095320623916811, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '4608377', 'n_tokens_mistral': 1159, 'n_tokens_neox': 1111, 'n_words': 256}