gitlab.com/evatix-go/core@v1.3.55/corevalidator/SliceValidator.go (about)

     1  package corevalidator
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  
     7  	"gitlab.com/evatix-go/core/constants"
     8  	"gitlab.com/evatix-go/core/enums/stringcompareas"
     9  	"gitlab.com/evatix-go/core/errcore"
    10  	"gitlab.com/evatix-go/core/internal/strutilinternal"
    11  )
    12  
    13  type SliceValidator struct {
    14  	ValidatorCoreCondition
    15  	CompareAs stringcompareas.Variant
    16  	// ActualLines considered to be actual
    17  	// ExpectedLines considered to be expected
    18  	ActualLines, ExpectedLines []string
    19  	comparingValidators        *TextValidators // lazy
    20  }
    21  
    22  func NewSliceValidatorUsingErr(
    23  	errActual error,
    24  	compareLinesContentAsExpected string,
    25  	isTrimLineCompare,
    26  	isNonEmptyWhitespace,
    27  	isSortStringsBySpace bool,
    28  	compareAs stringcompareas.Variant,
    29  ) *SliceValidator {
    30  	inputLines := errcore.ErrorToSplitLines(errActual)
    31  	compareLines := strings.Split(
    32  		compareLinesContentAsExpected,
    33  		constants.NewLineUnix)
    34  
    35  	return &SliceValidator{
    36  		ActualLines:   inputLines,
    37  		ExpectedLines: compareLines,
    38  		ValidatorCoreCondition: ValidatorCoreCondition{
    39  			IsTrimCompare:        isTrimLineCompare,
    40  			IsNonEmptyWhitespace: isNonEmptyWhitespace,
    41  			IsSortStringsBySpace: isSortStringsBySpace,
    42  		},
    43  		CompareAs:           compareAs,
    44  		comparingValidators: nil,
    45  	}
    46  }
    47  
    48  func NewSliceValidatorUsingAny(
    49  	anyValActual interface{},
    50  	compareLinesContentExpected string,
    51  	isTrimLineCompare,
    52  	isNonEmptyWhitespace,
    53  	isSortStringsBySpace bool,
    54  	compareAs stringcompareas.Variant,
    55  ) *SliceValidator {
    56  	anyToString := strutilinternal.AnyToString(anyValActual)
    57  	splitLines := strings.Split(anyToString, constants.NewLineUnix)
    58  	compareLines := strings.Split(
    59  		compareLinesContentExpected,
    60  		constants.NewLineUnix)
    61  
    62  	return &SliceValidator{
    63  		ActualLines:   splitLines,
    64  		ExpectedLines: compareLines,
    65  		ValidatorCoreCondition: ValidatorCoreCondition{
    66  			IsTrimCompare:        isTrimLineCompare,
    67  			IsNonEmptyWhitespace: isNonEmptyWhitespace,
    68  			IsSortStringsBySpace: isSortStringsBySpace,
    69  		},
    70  		CompareAs:           compareAs,
    71  		comparingValidators: nil,
    72  	}
    73  }
    74  
    75  func (it *SliceValidator) ActualLinesLength() int {
    76  	if it == nil {
    77  		return 0
    78  	}
    79  
    80  	return len(it.ActualLines)
    81  }
    82  
    83  func (it *SliceValidator) MethodName() string {
    84  	return it.CompareAs.Name()
    85  }
    86  
    87  func (it *SliceValidator) IsValidOtherLines(
    88  	isCaseSensitive bool,
    89  	otherActualLines []string,
    90  ) bool {
    91  	return it.
    92  		isValidLines(
    93  			isCaseSensitive,
    94  			otherActualLines)
    95  }
    96  
    97  func (it *SliceValidator) SetActual(
    98  	actual []string,
    99  ) *SliceValidator {
   100  	it.ActualLines = actual
   101  
   102  	return it
   103  }
   104  
   105  func (it *SliceValidator) SetActualVsExpected(
   106  	actual, expected []string,
   107  ) *SliceValidator {
   108  	it.ActualLines = actual
   109  	it.ExpectedLines = expected
   110  
   111  	return it
   112  }
   113  
   114  func (it *SliceValidator) ActualLinesString() string {
   115  	if it == nil {
   116  		return constants.EmptyString
   117  	}
   118  
   119  	return errcore.StringLinesToQuoteLinesToSingle(
   120  		it.ActualLines)
   121  }
   122  
   123  func (it *SliceValidator) ExpectingLinesString() string {
   124  	if it == nil {
   125  		return constants.EmptyString
   126  	}
   127  
   128  	return errcore.StringLinesToQuoteLinesToSingle(
   129  		it.ExpectedLines)
   130  }
   131  
   132  func (it *SliceValidator) ExpectingLinesLength() int {
   133  	if it == nil {
   134  		return 0
   135  	}
   136  
   137  	return len(it.ExpectedLines)
   138  }
   139  
   140  func (it *SliceValidator) ComparingValidators() *TextValidators {
   141  	if it.comparingValidators != nil {
   142  		return it.comparingValidators
   143  	}
   144  
   145  	validators := NewTextValidators(it.ExpectingLinesLength())
   146  
   147  	for _, line := range it.ExpectedLines {
   148  		validators.Add(TextValidator{
   149  			Search:                 line,
   150  			ValidatorCoreCondition: it.ValidatorCoreCondition,
   151  			SearchAs:               it.CompareAs,
   152  		})
   153  	}
   154  
   155  	it.comparingValidators = validators
   156  
   157  	return it.comparingValidators
   158  }
   159  
   160  func (it *SliceValidator) IsValid(isCaseSensitive bool) bool {
   161  	if it == nil {
   162  		return true
   163  	}
   164  
   165  	return it.isValidLines(
   166  		isCaseSensitive,
   167  		it.ActualLines)
   168  }
   169  
   170  func (it *SliceValidator) isValidLines(
   171  	isCaseSensitive bool,
   172  	lines []string,
   173  ) bool {
   174  	if it == nil && lines == nil {
   175  		return true
   176  	}
   177  
   178  	if lines == nil && it.ExpectedLines == nil {
   179  		return true
   180  	}
   181  
   182  	if lines == nil || it.ExpectedLines == nil {
   183  		return false
   184  	}
   185  
   186  	inputLength := len(lines)
   187  	comparingLength := len(it.ExpectedLines)
   188  
   189  	if inputLength != comparingLength {
   190  		return false
   191  	}
   192  
   193  	validators := it.ComparingValidators()
   194  
   195  	for i, validator := range validators.Items {
   196  		isNotMatch := !validator.IsMatch(
   197  			lines[i],
   198  			isCaseSensitive)
   199  
   200  		if isNotMatch {
   201  			return false
   202  		}
   203  	}
   204  
   205  	return true
   206  }
   207  
   208  func (it *SliceValidator) VerifyFirstError(
   209  	paramsBase *ValidatorParamsBase,
   210  ) error {
   211  	if it == nil {
   212  		return nil
   213  	}
   214  
   215  	return it.VerifyFirstLengthUptoError(
   216  		paramsBase,
   217  		it.ExpectingLinesLength())
   218  }
   219  
   220  func (it *SliceValidator) VerifyFirstLengthUptoError(
   221  	params *ValidatorParamsBase,
   222  	lengthUpTo int,
   223  ) error {
   224  	if it == nil {
   225  		return nil
   226  	}
   227  
   228  	return it.AllVerifyErrorUptoLength(
   229  		true,
   230  		params,
   231  		lengthUpTo)
   232  }
   233  
   234  func (it *SliceValidator) AllVerifyError(
   235  	params *ValidatorParamsBase,
   236  ) error {
   237  	if it == nil {
   238  		return nil
   239  	}
   240  
   241  	return it.AllVerifyErrorUptoLength(
   242  		false,
   243  		params,
   244  		it.ExpectingLinesLength())
   245  }
   246  
   247  func (it *SliceValidator) AllVerifyErrorTestCase(
   248  	caseIndex int,
   249  	isCaseSensitive bool,
   250  ) error {
   251  	if it == nil {
   252  		return nil
   253  	}
   254  
   255  	params := ValidatorParamsBase{
   256  		CaseIndex:                         caseIndex,
   257  		IsIgnoreCompareOnActualInputEmpty: false,
   258  		IsAttachUserInputs:                true,
   259  		IsCaseSensitive:                   isCaseSensitive,
   260  	}
   261  
   262  	err := it.AllVerifyErrorUptoLength(
   263  		false,
   264  		&params,
   265  		it.ExpectingLinesLength())
   266  
   267  	errcore.ErrPrintWithTestIndex(caseIndex, err)
   268  
   269  	return err
   270  }
   271  
   272  func (it *SliceValidator) AllVerifyErrorExceptLast(
   273  	params *ValidatorParamsBase,
   274  ) error {
   275  	if it == nil {
   276  		return nil
   277  	}
   278  
   279  	return it.AllVerifyErrorUptoLength(
   280  		false,
   281  		params,
   282  		it.ExpectingLinesLength()-1)
   283  }
   284  
   285  func (it *SliceValidator) AllVerifyErrorUptoLength(
   286  	isFirstOnly bool,
   287  	params *ValidatorParamsBase,
   288  	lengthUpto int,
   289  ) error {
   290  	if it == nil {
   291  		return nil
   292  	}
   293  
   294  	if it.isEmptyIgnoreCase(params) {
   295  		return nil
   296  	}
   297  
   298  	initialVerifyErr := it.initialVerifyErrorWithMerged(
   299  		params,
   300  		lengthUpto)
   301  
   302  	if initialVerifyErr != nil {
   303  		return initialVerifyErr
   304  	}
   305  
   306  	lengthErr := it.lengthVerifyError(params, lengthUpto)
   307  	if lengthErr != nil {
   308  		return lengthErr
   309  	}
   310  
   311  	validators := it.ComparingValidators()
   312  	var sliceErr []string
   313  	for i, validator := range validators.Items[:lengthUpto] {
   314  		err := validator.VerifySimpleError(
   315  			i,
   316  			params,
   317  			it.ActualLines[i])
   318  
   319  		if err != nil {
   320  			sliceErr = append(
   321  				sliceErr,
   322  				err.Error())
   323  		}
   324  
   325  		if isFirstOnly && err != nil {
   326  			break
   327  		}
   328  	}
   329  
   330  	if params.IsAttachUserInputs && len(sliceErr) > constants.Zero {
   331  		sliceErr = append(
   332  			sliceErr,
   333  			it.ActualInputWithExpectingMessage(params.Header))
   334  	}
   335  
   336  	return errcore.SliceToError(sliceErr)
   337  }
   338  
   339  func (it *SliceValidator) lengthVerifyError(
   340  	params *ValidatorParamsBase,
   341  	lengthUpto int,
   342  ) error {
   343  	hasLengthUpto := lengthUpto > constants.InvalidValue
   344  	comparingLength := it.ExpectingLinesLength()
   345  
   346  	var comparingLengthError error
   347  	if hasLengthUpto && lengthUpto > comparingLength {
   348  		comparingLengthError = errcore.OutOfRangeLengthType.Error(
   349  			"Asked comparingLength is out of range!",
   350  			comparingLength,
   351  		)
   352  	}
   353  
   354  	if comparingLengthError != nil {
   355  		return it.UserInputsMergeWithError(
   356  			params,
   357  			comparingLengthError)
   358  	}
   359  
   360  	var inputLengthErr error
   361  	if it.ActualLinesLength() > 0 && comparingLength == 0 {
   362  		inputLengthErr = errcore.LengthIssueType.Error(
   363  			"Input comparison has some text but comparing length is 0! Must set comparing text!",
   364  			comparingLength,
   365  		)
   366  	}
   367  
   368  	if inputLengthErr != nil {
   369  		return it.UserInputsMergeWithError(
   370  			params,
   371  			inputLengthErr)
   372  	}
   373  
   374  	return nil
   375  }
   376  
   377  // initialVerifyError, verifyLengthUpto less than 0 will check actual length
   378  func (it *SliceValidator) initialVerifyError(
   379  	lengthUpto int,
   380  ) error {
   381  	if it.ActualLines == nil && it.ExpectedLines == nil {
   382  		return nil
   383  	}
   384  
   385  	isAnyNilCase := it.ActualLines == nil ||
   386  		it.ExpectedLines == nil
   387  
   388  	if isAnyNilCase {
   389  		return errcore.ExpectingErrorSimpleNoType(
   390  			"ActualLines, ExpectedLines any is nil and other is not.",
   391  			it.ActualLines,
   392  			it.ExpectedLines,
   393  		)
   394  	}
   395  
   396  	if !it.isLengthOkay(lengthUpto) {
   397  		return errcore.ExpectingErrorSimpleNoType(
   398  			"ActualLines, ExpectedLines Length is not equal",
   399  			len(it.ActualLines),
   400  			len(it.ExpectedLines),
   401  		)
   402  	}
   403  
   404  	return nil
   405  }
   406  
   407  func (it *SliceValidator) isLengthOkay(lengthUpto int) bool {
   408  	inputLength := len(it.ActualLines)
   409  	comparingLength := len(it.ExpectedLines)
   410  	isLengthCheckUpto := lengthUpto > constants.InvalidValue
   411  	var isMinLengthMeet bool
   412  
   413  	if isLengthCheckUpto {
   414  		remainingInputLength := inputLength - lengthUpto
   415  		remainingCompareLength := comparingLength - lengthUpto
   416  
   417  		isMinLengthMeet = remainingInputLength == remainingCompareLength
   418  	}
   419  
   420  	isLengthOkay := isMinLengthMeet ||
   421  		inputLength == comparingLength
   422  
   423  	return isLengthOkay
   424  }
   425  
   426  func (it *SliceValidator) initialVerifyErrorWithMerged(
   427  	params *ValidatorParamsBase,
   428  	lengthUpto int,
   429  ) error {
   430  	initialVerifyErr := it.initialVerifyError(
   431  		lengthUpto)
   432  
   433  	if initialVerifyErr != nil {
   434  		return it.UserInputsMergeWithError(
   435  			params,
   436  			initialVerifyErr)
   437  	}
   438  
   439  	return nil
   440  }
   441  
   442  func (it *SliceValidator) ActualInputWithExpectingMessage(header string) string {
   443  	return it.ActualInputMessage(header) +
   444  		it.UserExpectingMessage()
   445  }
   446  
   447  func (it *SliceValidator) ActualInputMessage(header string) string {
   448  	return errcore.MsgHeaderPlusEnding(
   449  		actualUserInputsMessage+header,
   450  		it.ActualLinesString())
   451  }
   452  
   453  func (it *SliceValidator) UserExpectingMessage() string {
   454  	return errcore.MsgHeaderPlusEnding(
   455  		expectingLinesMessage,
   456  		it.ExpectingLinesString())
   457  }
   458  
   459  func (it *SliceValidator) isEmptyIgnoreCase(
   460  	params *ValidatorParamsBase,
   461  ) bool {
   462  	return params.IsIgnoreCompareOnActualInputEmpty &&
   463  		len(it.ActualLines) == 0
   464  }
   465  
   466  func (it *SliceValidator) UserInputsMergeWithError(
   467  	paramsBase *ValidatorParamsBase,
   468  	err error,
   469  ) error {
   470  	if !paramsBase.IsAttachUserInputs {
   471  		return err
   472  	}
   473  
   474  	if err == nil {
   475  		return errors.New(it.ActualInputWithExpectingMessage(paramsBase.Header))
   476  	}
   477  
   478  	msg := err.Error() +
   479  		it.ActualInputWithExpectingMessage(paramsBase.Header)
   480  
   481  	return errors.New(msg)
   482  }